ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高并发操作同一条数据,更新丢失数据问题(重复转账,票超卖,订单扣库存问题)

2020-10-01 08:33:23  阅读:265  来源: 互联网

标签:转账 库存 版本号 事物 余额 下单 超卖 数据


何为更新丢失数据问题:假设数据库中有一条数据,有两个事物A,B,同时对这条数据操作。事物A,B同时读到这条数据,事物A对这条数据进行修改并提交,然后事物B对这条数据修该改但晚于事物A提交。这种情况下事物B就会覆盖掉事物A的更新,事物A的更新就会丢失。这种情况有时会引起比较严重的问题。例如重复转账问题,例如一个账户A有100元余额,要向账户B进行转账100元的操作,通常会分为两步,首先读出账户A的余额,判断是否余额充足,然后进行转账扣款操作。如果同时有两个事物a,b进行这个操作,他们同时读到账户余额余额是100,于是他们都判断余额充足,事物A首先进行转账扣款操作,并提交。这个时候账户B已经得到100元转账,账户A余额是0.然后事物b,也进行转账扣款操作,并提交。这个时候,账户B再次得到100元转账,账户A的余额被修改成0.也就是说账户A最终扣款100,账户B却得到200元。票超卖问题也是类似的。

解决方案:1.在事物读取账户余额的语句中加排他锁,这样两个事物就无法同时读取到相同的余额。这种处理方法就是强制事物串行处理。缺点是并发量不高,处理的慢。

                  2.用乐观锁,给数据加乐观锁。也就是加一个版本号version字段。事物读取数据的同时,读取到版本号,提交的时候把版本号加一,并加上版本号判断。语句如下

                   update  table set Num=0,Version=Version-1 where Version=读到的版本号。这样如果事物A提交成功,版本号加一,事物B后提交时就会修改失败。可以根据修改影响的行数来判断。这样就可以避免更新丢失。可以根据业务进行重试。缺点并发量不能太高。

    以上两种解决方案都是数据库层面的。

下面在以电商抢购,下单与扣库存的业务场景提出如下两种解决方案:

                  3.将数据放到redis 缓存中。用分布式锁,强制同一时间只能有一个事务对数据操作,本质上也是将事务串行化操作。缺点并发量不高,而且必须保持数据库和缓存一致。

                  4.利用Redis increment 的原子操作(就是更新与读取是原子性的),保证库存安全。 事先需要把库存的数量等其他信息保存到Redis,并保证更新库存的时候,更新Redis。 进来的时候 先 get 库存数量是否充足,再执行 increment。以 increment > 0 为准。 检查库存 与 减少库存 不是原子性的。 检查库存的时候技术库存充足也不可下单;否则造成库存不安全,原来类似 方法1. increment 是个原子操作,已这个为准。

redisService.increment(key, -req.getNum().longValue()) >= 0 说明库存充足,可以下单。

redisService.increment(key, -req.getNum().longValue()) < 0 的时候 不能下单,次数库存不足。并且需要 回加刚刚减去的库存数量,否则会导致刚才减扣的数量 一直买不出去。数据库与缓存的库存不一致。

参考文章:https://blog.csdn.net/mifffy_java/article/details/95201752

次方法可以满足 高并抢购等一些方案,真正减扣库存和下单可以异步执行。

订单时效问题,订单取消等 为保证商家利益,同时把商品卖给有需要的人,订单下单成功后,往往会有个有效时间。超过这个时间,订单取消,库存回滚。

订单取消后,可利用MQ 回退库存等。缺点是如果redis 服务停止,将无法下单。

                 

 

标签:转账,库存,版本号,事物,余额,下单,超卖,数据
来源: https://www.cnblogs.com/gfbppy/p/13757249.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有