加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

并发扣款,如何保证数据的一致性?

发布时间:2019-08-31 03:21:44 所属栏目:建站 来源:58沈剑
导读:继承解答星球水友提问。 扣款的营业场景是奈何的? 用户购置商品的进程中,要对余额举办查询与修改,大抵的营业流程如下:第一步,从数据库查询用户现有余额: SELECTmoneyFROMt_yueWHEREuid=$uid; 不妨设查询出来的$old_money=100元。 第二步,营业层实验

继承解答星球水友提问。

扣款的营业场景是奈何的?

用户购置商品的进程中,要对余额举办查询与修改,大抵的营业流程如下:第一步,从数据库查询用户现有余额:

  1. SELECT money FROM t_yue WHERE uid=$uid; 

不妨设查询出来的$old_money=100元。

第二步,营业层实验营业逻辑计较,好比:

  • 先查询购置商品的价值,譬喻是80元;
  • 再查询产物是否有勾当,以及勾当折扣,譬喻是9折;
  • 比对余额是否足够,足够时才往下走;
  1. if($old_money> 80*0.9){ 
  2.     $new_money=$old_money-80*0.9=28 
  3. } else { 
  4.     return "Not enough minerals"; 

第三步,将数据库中的余额举办修改。

  1. UPDATE t_yue SET money=$new_money WHERE uid=$uid; 

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

统一个用户,并发扣款也许呈现什么题目?

在漫衍式情形中,假如并发量很大,这种“查询+修改”的营业有必然概率呈现数据纷歧致。

极限环境下,也许呈现这样的非常流程:

步调一,营业1和营业2并发查询余额,是100元。

并发扣款,怎样担保数据的同等性?

画外音:这些并发查询,是在差异的站点实例/处究竟例上完成的,历程内互斥锁必定办理不了。

步调二,营业1和营业2并发举办逻辑计较,算出各自营业的余额,假设营业1算出的余额是28元,营业2算出的余额是38元。

并发扣款,怎样担保数据的同等性?

步调三,营业1对数据库中的余额先举办修改,配置成28元。营业2对数据库中的余额后举办修改,配置成38元。

并发扣款,怎样担保数据的同等性?

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

画外音:假设营业1先写回余额,营业2再写回余额。

常见的办理方案?

对付此案例,统一个用户,并发扣款时,有小概率会呈现非常,可以对每一个用户举办漫衍式锁互斥,譬喻:在redis/zk里抢到一个key才气继承操纵,不然榨取操纵。

这种气馁锁方案确实可行,但要引入特另外组件(redis/zk),而且会低落吞吐量。

对付小概率的纷歧致,有没有乐观锁的方案呢?

对并发扣款举办进一步的说明发明:

(1) 营业1写回时,旧余额100,这是一个初始状态;新余额28,这是一个竣事状态。理论上只有在旧余额为100时,新余额才应该写回乐成。

而营业1并发写回时,旧余额确实是100,理应写回乐成。

(2) 营业2写回时,旧余额100,这是一个初始状态;新余额28,这是一个竣事状态。理论上只有在旧余额为100时,新余额才应该写回乐成。

可现实上,这个时辰数据库中的金额已经变为28了,以是营业2的并发写回,不该该乐成。

怎样低本钱实验乐观锁?

在set写回的时辰,加上初始状态的前提compare,只有初始状态稳固时,才应承set写回乐成,Compare And Set(CAS),是一种常见的低落读写锁斗嘴,担保数据同等性的要领。

此时营业要怎么改?

行使CAS办理高并发时数据同等性题目,只必要在举办set操纵时,compare初始值,假如初始值调动,不应承set乐成。

详细到这个case,只必要将:

  1. UPDATE t_yue SET money=$new_money WHERE uid=$uid; 
  2. 进级为: 
  3. UPDATE t_yue SET money=$new_money WHERE uid=$uid AND money=$old_money; 

即可。

并发操纵产生时:营业1执行:

  1. UPDATE t_yue SET money=28 WHERE uid=$uid AND money=100; 

营业2执行:

  1. 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的时辰,加上初始前提的比对即可。

优化不难,只改了半行SQL,但确实能办理题目。

但但愿各人有收成,思绪比结论重要。

【本文为51CTO专栏作者“58沈剑”原创稿件,转载请接洽原作者】

并发扣款,怎样担保数据的同等性?

戳这里,看该作者更多好文

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读