并发减库存遇到的一些问题及思考

最近在做公司电商产品的需求,通过多种方式了解了电商,针对商品设计的重点和难点个人感觉主要认为有两方面:

  1. 一是商品的多规格设计
  2. 二是分布式环境下库存并发增减的处理

 针对于库存的增减,处理不好很可能造成库存的超卖,及数据不一致问题(实际售出数量与针对于每个SKU库存的减量不一致,一般情况是售出数量多于SKU减量)现在讨论下针对于 高并发分布式环境库存的增减(防止超卖问题):

针对于单SKU减库存(每次只减一个库存)的操作:

方案一:

利用数据库行锁的特点,修改同一条数据,事务一中修改这条数据完毕 但事务还未提交,另一个事务中也需要修改该数据,到修改该数据操作时会一直等待,直到事务一提交事务释放行锁为止。事务二才会继续执行的特点(mysql更新操作默认的锁级别是行级的)。

update t_goods_sku t set t.goods_storage= t.storage - a where t.sku_id = b and t.goods_storage -a > 0

减库存失败则返回0 成功则返回受影响的行数(也就是1)。

也需大家会这样想,这样做肯定就万无一失了,利用mysql行锁的特性就能防止超卖现象的产生。其实考虑的还不够。如果你使用的是Oracle数据库,也许会达到你想要的效果(oracle默认的事务隔离级别是读已提交,其他事务提交的内容会在自己事务内及时的显现),如果是mysql并且采用默认的事务隔离级别的配置,在高并发环境下会出现问题(mysql事务隔离级别是可重复读,即其他事务修改的内容在自己事物里无法及时的显现,出现幻读的现象)。 需要针对默认的事务隔离级别做响应的修改。

所以如果对于单SKU增减的话 利用sql语句、行锁 、事务隔离级别的特点,针对于普通数据量,并发小的网站是可以满足需求的。

优点:实现简单,支持分布式,库存的实时性比较高

缺点:对数据库频繁操作导致数据库负载高

事务隔离级别可以通过设置mysql全局事务配置,也可以使用spring事务控制器中配置单事务隔离级别。

方案二:

单针对于以上缺点可以采用相应的优化手段,数据库中数据的操作主要包括读和写:

针对于读操作,可以采用分布式缓存处理,首先同步RDB 的SKU数据,读写操作

---------------------------------------未完待续

针对于多SKU批量减(每次减多个库存)操作:

方案一:

针对这个问题,如果是分布式环境,首先我们想到的是减库存这个操作 让位于不同机器上的程序去串行执行,这样就能保证一台机器的写操作对 另一台机器上的写数据可见。(可以采用分布式锁实现)

缺点:违背了分布式的设计初衷,不同机器上的程序并行执行的初衷被违背了,并且串行执行只能单节点执行某段程序,导致程序效率极其低下。

方案二:

参考文章:https://my.oschina.net/LucasZhu/blog/1798655

猜你喜欢

转载自my.oschina.net/LucasZhu/blog/1798656
今日推荐