详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt395

缘起:在高并发的分布式环境下,对于数据的查询与修改容易引发一致性问题,本文将分享一种非常简单但有效的优化方法。

一、业务场景

业务场景为,购买商品的过程要对余额进行查询与修改,大致的业务流程如下:

(1)从数据库查询用户现有余额 SELECT money FROM t_yue WHERE uid=$uid,不妨设查询出来的$old_money=100元

(2)业务层实施业务逻辑,比如购买一个80元的商品,并且打九折

if($old_money> 80*0.9) $new_money=$old_money-80*0.9=28

(3)将数据库中的余额进行修改 UPDAtE t_yue SET money=$new_money WHERE uid=$uid

在并发量低的情况下,这个流程没有任何问题,原有金额100元,购买了80元的九折商品(72元),剩余28元。

二、潜在的问题

在分布式环境中,如果并发量很大,这种“查询+修改”的业务很容易出现数据不一致。极限情况下,可能出现这样的异常流程:

(1)业务1和业务2同时查询余额,是100元

(2)业务1和业务2进行逻辑计算,算出各自业务的余额,假设业务1算出的余额是28元,业务2算出的余额是38元

(3)业务1对数据库中的余额先进行修改,设置成28元。

业务2对数据库中的余额后进行修改,设置成38元。

此时异常出现了,原有金额100元,业务1扣除了72元,业务2扣除了62元,最后剩余38元。

三、问题原因

高并发环境下,对同一个数据的并发读(两边都读出余额是100)与并发写(一个写回28,一个写回38)导致的数据一致性问题。

四、原因分析

业务1的写回:原有金额100,这是一个初始状态,写回金额28,理论上只有在原有金额为100的时候才允许写回成功,这一步没问题。

业务2的写回:的原有金额10038100的时候才允许写回成功,可实际上,这个时候数据库中的金额已经变为28了,这一步的写操作不应该成功。

五、简易解决方案

在set写回的时候,加上初始状态的条件compare,只有初始状态不变时,才允许set写回成功,这正是大家常说的“Compare And Set”(CAS),是一种常见的降低读写锁冲突,保证数据一致性的方法。

六、业务的升级

业务线使用CAS解决高并发时数据一致性问题,只需要在进行set操作时,compare一下初始值,如果初始值变换,不允许set成功。

对于上文中的业务场景,只需要将“UPDAtEt_yue SET money=$new_money WHERE uid=$uid”升级为

UPDAtE t_yue SETmoney=$new_money WHERE uid=$uid AND money=$old_money”即可。

并发操作发生时:

业务1执行 => UPDAtE t_yue SET money=28 WHERE uid=$uid AND money=100

业务2执行SET money=38 WHERE uid=$uid

【这两个操作同时进行时,只能有一个执行成功】。

七、怎么判断哪个执行成功,哪个执行失败

set操作,其实无所谓成功或者失败,业务能通过affect rows得知哪个修改没有成功:

执行成功的业务,为1

执行失败的业务,为0

八、总结

高并发“查询并修改”的场景,可以用CAS(Compare and Set)的方式解决数据一致性问题。对应到业务,即在set的时候,加上初始条件的比对。

用CAS方案解决高并发一致性问题的更多相关文章

  1. asp.net解决高并发的方案.

    asp.net解决高并发的方案. Posted on 2012-11-27 22:31 75077027 阅读(3964) 评论(1) 编辑 收藏 最近几天一直在读代震军的博客,他是 Discuz!N ...

  2. php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结)

    php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结) 一.总结 从外到内解决网站大流量高并发问题---从提交一个url开始(从用户按下搜索栏回车键开始) url最开始会到d ...

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

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

  4. Nginx和Tengine解决高并发和高可用,而非推荐Apache

    什么是Nginx  什么是Tengine 看看国内大公司在用Nginx和Tengine吗? 步骤一:进入 https://www.taobao.com/,按F12.可看到 有很多APP对淘宝进行请求. ...

  5. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  6. 转发:php解决高并发

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

  7. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

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

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

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

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

随机推荐

  1. CGLib方式对接口实现代理

    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采 ...

  2. UITabbarController左右滑动切换标签页

    UITabbarController左右滑动切换标签页 每个Tabbar ViewController都要添加如下代码,建议在基类中添加:ViewDidLoadUISwipeGestureRecogn ...

  3. hdu--5351--MZL's Border

    表示看这篇博客后找到了思路: http://blog.csdn.net/queuelovestack/article/details/47291195 补充一下数据,方便观察规律 m  LBorder ...

  4. Springboot+redis 整合

    运行环境: JDK1.7. SpringBoot1.4.7 redis3.0.4 1.生成Springboot项目,分别添加web,redis依赖,具体的maven依赖如下 <dependenc ...

  5. Java微信公众平台开发之OAuth2.0网页授权

    根据官方文档点击查看在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的"开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息"的配置选项中,修 ...

  6. 如何解压 Mac OS X 下的 PKG 文件(网摘)

    如何解压 Mac OS X 下的 PKG 文件 原文出处:[Macplay] 有时候我们可能需要解包 PKG 格式的安装文件包,在 OS X 系统下完成该操作并不需要你额外再安装软件,系统内置的命令就 ...

  7. 升级Cocoapods引起的Mantle库找不到的问题及解决方法

    年前升级了Cocoapods库,从0.39升级到了1.2.0-beta版,然后用模拟器和真机测试都是没有问题的,均可以成功编译.今天测试人员要测试包,准备archive打包时,却提示:ld: libr ...

  8. centos 7.2 配置Nginx

    1.添加资源 添加CentOS 7 Nginx yum资源库,打开终端,使用以下命令(没有换行): rpm -Uvh http://nginx.org/packages/centos/7/noarch ...

  9. Oracle锁表查询与解锁

    锁表查询和解锁 --查询SELECT object_name, machine, s.sid, s.serial# FROM gv$locked_object l, dba_objects o, gv ...

  10. elasticsearch映射

    前面讲到,无论是关系型数据库还是非关系型数据库,乃至elasticsearch这种事实上承担着一定储存作用的搜索引擎,数据类型都是非常重要而基础的概念.但elasticsearch与其它承担着数据存储 ...