文档章节

高并发下的数据一致性问题

橙子666
 橙子666
发布于 2017/09/10 19:01
字数 963
阅读 51
收藏 1

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

 

一、业务场景

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

(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的写回:的原有金额100,这是一个初始状态,写回金额38,理论上只有在原有金额为100的时候才允许写回成功,可实际上,这个时候数据库中的金额已经变为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执行 => UPDAtE t_yue SET money=38 WHERE uid=$uid AND money=100

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

 

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

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

执行成功的业务,affect rows为1

执行失败的业务,affect rows为0

 

八、总结

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

本文转载自:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=400556481&idx=1&sn=42bc187b45e4e53aece4b8c1f43

共有 人打赏支持
橙子666
粉丝 1
博文 72
码字总数 46552
作品 0
杭州
程序员
私信 提问
如此牛逼?双11背后的秘密-支付宝app双11最佳实践

近来,FF项目的运营活动越来越多,对于架构设计以及程序研发有了更高的要求,参考国内互联网公司对于营销活动app的设计思路,我们找到了最具有代表性的支付宝双11活动,阐述运营活动类高并发...

丁小晶
2016/04/20
0
0
高并发和高性能系统中数据一致性问题和应对

读过前面一篇文章《系统架构升级之道,关注关键服务依赖》就知道,我们的应用系统中的关键服务绝大部分都会是对数据库的依赖。 如果只有一个数据库服务器,数据一致性问题也就不存在了。 可是...

一凡Sir
06/21
0
0
关于高并发,高响应的架构是长什么样的啊?求大神不吝赐教!

和别人聊天,被问起高并发高响应的架构该怎么实现,发现对此一无所知,不知哪位能够解答一下,万分感谢 稍微加两句: 并发的时候采用集群 响应的话我觉得采用缓存 还有得保证数据的一致性 对...

首席撸出血
2015/07/30
113
1
巧用CAS解决数据一致性问题

一、业务场景 业务场景为,购买商品的过程要对余额进行查询与修改,大致的业务流程如下: (1)从数据库查询用户现有余额 SELECT money FROM tyue WHERE uid=$uid,不妨设查询出来的$oldmon...

懂得-奉献
2016/12/02
24
0
NRedis-Proxy 高性能Redis 中间件服务原理解析

受飞凡电商技术负责人刘兵先生的独家授权,在csdn博客我原创发表《NRedis-Proxy 高性能Redis 中间件服务》的架构原理,以及项目开源介绍。 一、 NRedis-Proxy 介绍 NRedis-Proxy 是一个Redis...

colincheng
2016/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mgo初步接触

Intro mgo是mongodb的go语言绑定,第一次在静态类型语言中使用ORM,故留个笔记。 模型 mongodb是schema-less无模式的NoSQL非关系型数据库,理论上来说,在同一个表(mongodb中称为collectio...

御坂网络路由器
11分钟前
2
0
不要忽略异常(65)

请不要忽略异常, 尤其在api方法声明将会抛出的异常,这是定义者在试图说明某种问题 空的catch 块起到忽略异常的作用 对空的catch 块保持警惕,不应该出现 至少也要写明忽略该异常的原因 有一...

Java搬砖工程师
12分钟前
1
0
网站漏洞检测工具对discuzX3.2 X3.4网站漏洞修复

2018年12月9日,国内某安全组织,对discuz X3.2 X3.4版本的漏洞进行了公开,这次漏洞影响范围较大,具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞,也俗称SSRF漏洞,漏洞产生的原因首先...

网站安全
12分钟前
2
0
2018开发人员路线图

chinahufei
14分钟前
2
0
领哥,项目管理

领哥 https://www.leangoo.com/kanban/board_list

miaojiangmin
27分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部