很多做过电商系统的人应该知道,我们在设计电商系统中关于商品库存扣减时,在大部分情况下(并发量不高时),商品库存都可以直接在关系型数据库中进行扣减,那么在限时抢购活动正式开始后,那些单价比平时更给力、更具吸引力的热卖商品大家肯定都会积极踊跃地参与抢购,这必然会产生大量针对数据库同一行记录的并发更新操作。因此数据库为了保证原子’性, InnoDB 引擎默认会对同一行数据记录加锁,把前端的并发请求变成串行操作,以确保数据更新时的正确性。
 
如果直接在数据库中扣减库存,应该如何避免商品超卖呢?
 
在生产环境中我们可以通过乐观锁机制来避免这个问题。所谓乐观锁,简单来说,就是在 item表中建立一个 version 字段。假设某一个热卖商品的实际库存为n,出于对性能的考虑,查询库存操作是不建议加 for update (悲观锁,代价太大)的,那么在并发场景下,必然会导致多个用户拿到的 stock 和 version都一样。因此当第1个用户成功扣减商品库存后, 需要将 item表中的 version加1, 当第 2个用户扣减库存时,由于 version 不匹配,那么无法扣减成功,并且会抛出:StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)的异常。
 
当然,对于乐观锁一般的做法,是较为友好的提醒用户:“数据已经被其他人更改,请重新操作!”。可能一般系统这种方式可行,但是对于高并发的电商系统来讲,这就非常不友好,甚至直接导致客户大面积流失,那么有没有相对较为好的解决方案呢?
 
实际上,我们可以这样干
 
为了提升库存扣减的成功率,可以适当进行重试,如果库存不足,则说明商品已经售罄,反之扣减库存后 version 继续加1 。关于在数据库中使用乐观锁扣减库存的伪代码,如下所示:
除了使用乐观锁,还可以在扣减商品库存时,利用“实际库存数 大于 扣减库存数” 作为条件来替代 version 匹配,防止商品超卖。相对于乐观锁,采用这种方式会更加
直接,由于充分利用了 InnoDB 引擎提供的行锁特性,因此大大提升和保障了库存扣减的成功率,如下所示:
 
/* 实际库存数 大于 扣减库存数*/
UPDATE item SET stock=stock - 扣减库存数 WHERE item id=l AND stock >= 扣减库存数
 
两种方案均能够有效避免商品超卖,当然还是推荐使用乐观锁的使用方案。
 
 
 
 

最新文章

  1. Android-RelativeLayout(相对布局)、LinearLayout(线性布局)
  2. 利用C语言获得网页编码
  3. c# 中基类变量指向派生类对象的实例化
  4. Android 3D滑动菜单完全解析,实现推拉门式的立体特效
  5. Python中布尔类型
  6. 11.Warning (332060): Node: pi_fck3p was determined to be a clock but was found without an associated clock assignment.
  7. supervisor进程管理
  8. chrome性能测试框架webpagereplay
  9. 【COCOS2DX-游戏开发之三三】TMX边界控制与小窗体内预览TMX
  10. [poj 1127]Jack Straws[线段相交][并查集]
  11. WebService它CXF这三个音符(Service接口实现类)
  12. CentOS7.3虚拟机双网卡配置
  13. BZOJ 3622: 已经没有什么好害怕的了 [容斥原理 DP]
  14. PORTE_ISFR & (1<<n)
  15. iOS MVVM架构总结
  16. 关于mpvue 切换页面数据没清空
  17. java-过滤器、拦截器
  18. linux windows 传输文件
  19. eclipse打jar包解决第三方依赖包
  20. rem是如何实现自适应布局的

热门文章

  1. kdevelop 是什么 什么鬼(windows系统非linux)
  2. vue中如何在本地导入js文件
  3. 三、通过 FactoryBean 来配置bean
  4. 尝试在阿里云的Linux服务器器上安装拥有图形界面的Pycharm
  5. PHP反序列化中过滤函数使用不当导致的对象注入
  6. web开发发展历程
  7. Codeforces_492_E
  8. 为什么尽量不要使用Executors创建线程池
  9. 初学maven的一些配置
  10. linux下使用gdb对php源码调试