购物并发之商品库存

来源:互联网 发布:安卓微信语音导出软件 编辑:程序博客网 时间:2024/04/30 09:25
      购物网站的并发,这个问题也算是老生常谈的,很多大的电商网站都对这块的技术和业务,有了非常缜密的安排和设计。但是实际上在一些小型的系统中,对于这块内容的处理往往是缺乏规划和经验的。

问题分析

      最近也是在项目的测试中出现了商品库存的问题,因此通过review代码,也发现了商品订单及支付这一块对并发购买的处理是存在问题的。商品库存,作为购物流程中修改的最频繁的数据,无疑是值得重视的。      在这个问题提出的同时,根据我的一些经验,我也同时大致想到了几种看似能够解决问题的手段:数据库锁、缓存及业务手段。      关于缓存,本项目用的memcached,memcached比起redis,数据类型比较单一,序列化不方便,优点是读取效率高一些,实际上解决业务问题的能力上还是不如redis的。      对于数据库的锁,在网站日常的运行过程中,使用数据库锁完全可以解决库存超卖的问题,但是我相信稍大一些的系统都是不会这么做的。因为对于电商网站常用的Innodb来说,表级锁开销小,加锁快,不会出现死锁,发生锁冲突的概率最高,并发度最低;行级锁开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。库存问题如果使用数据库的行级锁解决,就很难避免死锁的问题,更别提网站搞些活动,一些请求高峰的时段如此频繁的锁操作会对系统的体验造成怎样的影响了。      关于业务手段,实际上,项目中也是用到了这种手段:在下单时就修改商品库存,在支付时再次比对库存,一旦这样做了,也有一些缺点,比如恶意下单的问题————一些人下完单不买,耗光库存,商品卖不出去。另外一个问题就是,两个人都下单成功,支付的时候都不能买,而实际上第一个人在下单的时候库存确确实实是存在的,但他却仍然无法购买商品,这就造成了最后几件商品可能无法被利用的情况,造成了资源浪费。

方案设计

基于以上几种考虑,我综合给出了这样两种搭配使用的方案:


      首先,下单减库存,存在一些缺点,但也有好处,那我们是不是可以给库存设定一个阈值呢?          因此我的方案是:默认情况下,当库存大于阈值时采用支付减库存的方式,当库存小于阈值的时候采用下单减库存的方式。同时,商家也可以自己设置究竟使用哪种减库存的方案。      另外,对于缓存的应用,我的方案是内存锁:当某个用户修改某个id的商品库存时,将商品id存放到memcached中,若其他用户要对商品库存进行操作时,如果读到memcached有这个id值,就阻止这个用户,而之前的用户操作完毕后,删除memcached中的数据。这个思路其实本质上和悲观锁是一致的!但是memcached的操作速度远远大于结构化数据库,而且是项目架构现成的技术。      以上就是我参考的不少资料和朋友的想法,提出的解决方案。

总结

    写了这么多,在这个问题上总算也有了一个交代,但是如果把这些粗浅的想法放到类似于淘宝那样的大并发网站上去的话,无疑会有更多的问题出现。但之前我也向一位技术总监级别的大牛请教过类似的问题,用他的话来说,淘宝的库存都是存在预留的,不会说仓库里10件商品,就在库存中填10。    因此,不是所有问题都是能用技术解决的,而我们只能尽量做到最好,这句话,每个做技术的人都应该铭记于心。
0 0