悲观锁 vs 乐观锁 vs Redis
企业面对高并发场景采用的方案.
比如 产品抢购高并发时的超发现象.
1 悲观锁
悲观锁 需要数据库本身提供支持(Oracle和MySQL都是支持的).
实现细节:
当前 数据库事务 读取到产品后, 就将目标数据直接锁定(select ... for update), 不允许别的线程进行读写操作, 知道 当前数据库事务完成自动释放锁.
悲观锁中, 资源只能被一个事务锁持有, 所以也被称为 独占锁 or 排它锁.
悲观锁的优点是实现简单好理解, 缺点是过多的等待和响应的事务切换导致性能问题.
为提高运行效率, 可以采用 乐观锁.
2 乐观锁
乐观锁 是一种 不使用数据库锁 和 不阻塞线程并发 的方案.
著名的 CAS(Compare and Swap): 线程在修改目标数据时, 会将目标数据的当前状态和旧状态进行比较(Compare), 如果状态一直, 就可以认为 数据木有被修改过, 否则就认为数据已经不同步了, 当前计算作废, 不做任何修改操作(回滚).
CAS方案却会引发 ABA问题, 就是共享值回退导致数据的不一致问题, 有点像脏读.
采用 带版本号(version)的乐观锁方案, 再配合CAS, 就可以解决 ABA问题了.
实现细节:
给产品表添加 version字段, 只要操作过程中有修改产品状态(比如减少库存), 无论是业务正常 回退 还是异常, 版本号只增不减. 即
update t_product set stock=stock-#{quantity}, version=version+1
where id=#{id} and version=#{version}
乐观锁没有独占资源和阻塞任何线程, 所以乐观锁也称为 非独占锁 or 无阻塞锁.
在实际使用乐观锁时, 会发现线程的业务失败率会很高, 针对这点可以对 乐观锁 引入重入机制. 也就是一旦业务失败, 不是立即结束请求, 而是重新做一次乐观锁流程, 可限制重入时间or重入次数.
乐观锁优点是不独占不阻塞, 缺点是实现相对复杂.
3 Redis
有些企业已经开始使用 NoSQL 来处理高并发问题, 代表就是 Redis(内存数据库).
首先, Redis 是内存数据库, 所以性能是没的说的. 其次, Redis Lua 在 Redis 的执行中是具备原子性的, 所以不会发送超发现象.
两步设计:
1) 使用 Redis 响应高并发用户请求
即用 Redis 代替原来的磁盘数据库 读写, 保证性能和数据一致性.
2) 定时持久化 Redis 数据
内存数据存储是不稳定的, 我们需要及时将保存在内存中的数据持久化到磁盘数据库中.
使用 Redis 效率要比悲观锁和乐观锁机制快上数倍, 但是千万记住 Redis 的存储基于内存, 如果操作不当容易引发数据的丢失, 所以使用 Redis 时建议使用独立的 Redis 服务器, 而且要做好备份和容灾等手段.
参考:
https://www.cnblogs.com/zhiqian-ali/p/6200874.html
<<深入浅出 Spring Boot 2.x>> 杨开振
悲观锁 vs 乐观锁 vs Redis的更多相关文章
- mysql-mysql悲观锁和乐观锁
1.mysql的四种事务隔离级别 I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题. (1)脏读: 对于两个事物 T1, T2, T1 ...
- Hibernate解决高并发问题之:悲观锁 VS 乐观锁
高并发问题是程序设计所必须要解决的问题,解决此类问题最主要的途径就是对对程序进行加锁控制.hibernate对加锁机制同样做出了实现,常用加锁方式为悲观锁和乐观锁.悲观锁指的是对数据被外界(包括本系统 ...
- mysql的锁--行锁,表锁,乐观锁,悲观锁
一 引言--为什么mysql提供了锁 最近看到了mysql有行锁和表锁两个概念,越想越疑惑.为什么mysql要提供锁机制,而且这种机制不是一个摆设,还有很多人在用.在现代数据库里几乎有事务机制,aci ...
- Oracle数据库悲观锁与乐观锁详解
数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁.什么叫悲观锁呢,悲观锁顾名思义,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住.而乐 ...
- 025 hibernate悲观锁、乐观锁
Hibernate谈到悲观锁.乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差 并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了.称为并发性不好 数据库隔离级 ...
- Mysql锁机制--乐观锁 & 悲观锁
Mysql 系列文章主页 =============== 从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁.所以本文将对锁(乐观锁.悲观锁)进行分析. 第一部分 悲观锁 ...
- Mysql共享锁、排他锁、悲观锁、乐观锁及其使用场景
一.相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁定一行) |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁) |--悲观锁( ...
- MySQL学习笔记(四)悲观锁与乐观锁
恼骚 最近在搞并发的问题,订单的异步通知和主动查询会存在并发的问题,用到了Mysql数据库的 for update 锁 在TP5直接通过lock(true),用于数据库的锁机制 Db::name('p ...
- 多线程深入:乐观锁与悲观锁以及乐观锁的一种实现方式-CAS(转)
原文:https://www.cnblogs.com/qjjazry/p/6581568.html 首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每 ...
随机推荐
- 【MySQL】
org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; Lock wait timeout exc ...
- Android Studio "cannot resolve symbol R" 问题
初接触Android Studio,又遇到了 "cannot resolve symbol R"问题(以前在 Eclipse 也遇到过),网上方法不一,后来在stackoverfl ...
- 【SVN】SVN Working copy is too old
前天在使用 SVN 客户端 CornerStone 的时候遇到了这个问题,代码不能提交了…… 遇到这个问题的时候怎么办? 解决办法: 找到报错对应的文件夹,里面有个 .svn 的文件夹,去掉再 com ...
- spring boot 学习笔记(二)之打包
一.叙述 spring boot 在 pom 中可以配置成 packaging 为 jar ,这样打包出来的就是一个 jar 包,可以通过 Java 命令直接运行, Java 命令为: java - ...
- 通过自制yum源离线安装ansible
系统环境 --CentOS release 7 python版本--Python 3.5.4 背景:在企业环境中,安装ansible的服务器往往不能访问互联网,简单的下载ansible源码安装,会 ...
- Redis优化建议
优化的一些建议 1.尽量使用短的key 当然在精简的同时,不要完了key的"见名知意".对于value有些也可精简,比如性别使用0.1. 2.避免使用keys * keys *, ...
- JNDI----数据连接池
JNDI:提供了查找和访问各种命名和目录服务的通用,统一的接口 常用的配置属性: name:表示以后要查找的名称.通过此名称可以找到DataSource,此名称任意更换,但是程序中最终要查找的就是 ...
- 图片格式:gif / png / pg / webp 介绍
本文引自:https://www.cnblogs.com/changyangzhe/articles/5718285.html GIF介绍 GIF 意为Graphics Interchange for ...
- 分析android studio的项目结构
以最简单的工程为例子,工程名为随意乱打的Exp5,新建好工程后将项目结构模式换成android: 1.manifests AndroidManifest.xml:APP的配置信息 <?xml v ...
- C++ “::” 作用域符 双冒号
C++ "::" 作用域符 双冒号 作用域符 :: 是作用域符,是运算符中等级最高的,它分为三种: 1)global scope(全局作用域符),用法(::name) 2)clas ...