详见: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. 关于Visual Studio调试 无效指针提示

    前几天遇到了这个问题,编译没问题,直接运行没问题 但是一调试,会提示无效指针,(按Ctrl+F5可以运行,但按F5提示无效指针) 只要这样,新建C:\ProgramData\Microsoft Vis ...

  2. JavaScript addEventListener 第三个参数

    先看一个完整的演示页面代码. Code <!DOCTYPE html> <html lang="zh-CN"> <head> <meta ...

  3. struts2相关简单介绍

    一 Struts2环境配置 1.准备jar包,核心jar包有: 2.创建Struts2项目并导入jar包 3.在Struts2项目中src下创建Struts.xml配置文件 4.在Web.xml文件中 ...

  4. Hello world! My first blog!

    Hello world! My first blog!

  5. 【head first python】学习计划

    1 初识Python:人人都爱列表 2 共享你的代码:函数模块 3 文件与异常:处理错误 4 持久存储:数据保存到文件 5 推导数据:处理数据! 6 定制数据对象:打包代码与数据 7 Web开发:集成 ...

  6. Coursera scala课程第一周答案

    Exercise 1: Pascal's Triangle The following pattern of numbers is called Pascal's triangle. 1 1 1 1 ...

  7. mac使用小提示

    1. 升级到serria系统,默认需要长按caps lock 才会锁定,段按会切换输入法.解决方法: 设置--键盘--输入法,  取消勾选"使用大写锁定键切换输入法" 2. 是否显 ...

  8. MySQL中的数据类型及创建

    MySQL创建: 1.创建数据库create database test2; 2.删除数据库drop database test2;3.创建表create table ceshi(    ids in ...

  9. SQL-三级分类查询

    /*SQLyog 企业版 - MySQL GUI v8.14 MySQL - 5.5.40 : Database - appinfodb******************************** ...

  10. Orleans---持久化

    Orleans配置---持久化 这是Orleans系列文章中的一篇.首篇文章在此 Grain理想的生命周期应该如下图所示: 这就如美国电影中的大反派一样,死了再复活,死了再复活.当然如果复活的反派没有 ...