在解决高并发问题时,如果是分布式系统显然我们只能够使用数据库端加锁机制来解决这个问题,但是这种同步机制或者数据库物理锁机制会牺牲一部分的性能,所以常常以另外一种方式来解决这个问题 就是乐观锁模式

  银行两操作员同时操作同一账户就是典型的乐观锁模式。
      比如A、B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后提交。最后实际账户余额为1000-50=950元,但本该为1000+100-50=1050。这就是典型的并发问题。

乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。

  读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

  对于上面修改用户帐户信息的例子而言,假设数据库中帐户信息表中有一个version字段,当前值为1;而当前帐户余额字段(balance)为1000元。假设操作员A先更新完,操作员B后更新。
a、操作员A此时将其读出(version=1),并从其帐户余额中增加100(1000+100=1100)。
b、在操作员A操作的过程中,操作员B也读入此用户信息(version=1),并从其帐户余额中扣除50(1000-50=950)。
c、操作员A完成了修改工作,将数据版本号加一(version=2),连同帐户增加后余额(balance=1100),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录version更新为2。
d、操作员B完成了操作,也将版本号加一(version=2)试图向数据库提交数据(balance=950),但此时比对数据库记录版本时发现,操作员B提交的数据版本号为2,数据库记录当前版本也为2,不满足 “提交版本必须大于记录当前版本才能执行更新 “的乐观锁策略,因此,操作员B的提交被驳回。
这样,就避免了操作员B用基于version=1的旧数据修改的结果覆盖操作员A的操作结果的可能。

操作员A操作如下:

select id, balance, version from account where id="1";
查询结果:id=1, balance=1000, version=1update account
set balance=balance+100, version=version+1
where id="1" and version=1select id, balance, version from account where id="1";
查询结果:id=1, balance=1100, version=2

操作员B操作如下:

select id, balance, version from account where id="1";
查询结果:id=1, balance=1000, version=1#操作员A已修改成功,实际account.balance=1100、account.version=2,操作员B也将版本号加一(version=2)试图向数据库提交数据(balance=950),但此时比对数据库记录版本时发现,操作员B提交的数据版本号为2,数据库记录当前版本也为2,不满足 “提交版本必须大于记录当前版本才能执行更新 “的乐观锁策略,因此,操作员B的提交被驳回。
update account
set balance=balance-50, version=version+1
where id="1" and version=1 select id, balance, version from account where id="1";
查询结果:id=1, balance=1100, version=2

  Hibernate、JPA等ORM框架或者实现,是使用版本号,再判断UPDATE后返回的数值

Demo: https://blog.csdn.net/xiaojin21cen/article/details/79439373

乐观锁 -业务判断 解决高并发问题相关推荐

  1. 借助Redis锁,完美解决高并发秒杀问题

    欢迎关注方志朋的博客,回复"666"获面试宝典 场景:一家网上商城做商品限量秒杀. 1 单机环境下的锁 将商品的数量存到Redis中.每个用户抢购前都需要到Redis中查询商品数量 ...

  2. mysql乐观锁 秒杀_使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法...

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

  3. Redis锁解决高并发问题

    Redis锁解决高并发问题 redis真的是一个很好的技术,它可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动. redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们 ...

  4. PHP利用Mysql锁解决高并发

    前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ...

  5. 利用Redis锁解决高并发问题

    利用Redis锁解决高并发问题 参考文章: (1)利用Redis锁解决高并发问题 (2)https://www.cnblogs.com/yszr/p/11698696.html 备忘一下.

  6. 转发:php解决高并发

    php解决高并发(转发:https://www.cnblogs.com/walblog/articles/8476579.html) 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Pe ...

  7. asp.net怎样解决高并发问题

    队列+多线程+couchbase缓存 ,解决高并发问题. using System; using System.Collections.Generic; using System.Linq; usin ...

  8. 每一个程序员都应该知道的高并发处理技巧、创业公司如何解决高并发问题、互联网高并发问题解决思路、caoz大神多年经验总结分享...

    本文来源于caoz梦呓公众号高并发专辑,以图形化.松耦合的方式,对互联网高并发问题做了详细解读与分析,"技术在短期内被高估,而在长期中又被低估",而不同的场景和人员成本又导致了巨头 ...

  9. Spring Boot实战解决高并发数据入库: Redis 缓存+MySQL 批量入库

    前言 最近在做阅读类的业务,需要记录用户的PV,UV: 项目状况:前期尝试业务阶段: 特点: 快速实现(不需要做太重,满足初期推广运营即可) 快速投入市场去运营 收集用户的原始数据,三要素: 谁 在什 ...

最新文章

  1. nullptr和NULL
  2. loadrunner使用流程_LoadRunner关联函数
  3. 裁剪Linux小系统
  4. c# 再次尝试 连接失败_修复破裂婚姻,如何重新建立情感连接
  5. 第一个 python for maya
  6. 0/1背包问题——动态规划方法
  7. C#中静态方法和非静态方法的区别
  8. 语言逻辑运算符两侧运算对象_5.3 C语言逻辑运算符与表达式
  9. webpack多个Html,使用webpack构建多页面应用
  10. BZOJ 5277 IQ题orz
  11. Chrome扩展之书签
  12. Python 轻松操作Excel,实现自动化办公
  13. 有监督 VS 无监督
  14. java代码对图片缩放
  15. 星星泡饭伴奏_星星泡饭 - Ayo_Lvlv - 5SING中国原创音乐基地
  16. TransBigData:一款基于 Python 的超酷炫交通时空大数据工具包
  17. matlab移相法实现单边带调制,移相法实现单边带信号的调制
  18. linux如何连接手机传文件,Ubuntu和手机通过蓝牙互传文件
  19. 博客园自定义(全部样式分享)
  20. SpringBoot之监控器/AOP/拦截器的使用及执行顺序

热门文章

  1. 解决报错:Can't read private key和./build-aux/cksum-schema-check: Permission denied
  2. linux 同步方法剖析,Linux 同步方法剖析
  3. c++ 打开添加删除程序_Docker 添加容器到一个网络
  4. java 网络编程简单聊天_网络编程之 TCP 实现简单聊天
  5. 值类型 与引用的 copy
  6. QuartzCore框架-- iOS中的动画
  7. MVC Razor模板引擎
  8. channelinboundhandler中都包含了哪一类的方法_数据仓库、数据集市、数据湖、数据中台到底有什么区别?都得做吗?...
  9. 将毫秒转换_Matlab将Unix时间戳转为可读日期
  10. linux 文件缓冲区,如何查看 Linux 当前缓存了哪些大文件?