zoukankan      html  css  js  c++  java
  • 秒杀核心设计(减库存部分)--防超卖与高并发

    from: http://www.tuicool.com/articles/Bfa63e6

                  商品详情页面的静态化,varnish加速,秒杀商品库独立部署服务器这种就略过不讲了。只讨论库存部分的优化
          mySQL配置层面的优化可以参考我的这篇文章    《关于mysql innodb引擎性能优化的一点心得》  
      重点设计在数据库层面。
      2张表:
      第一张:判重表(buy_record),该用户有没秒杀过该商品
      字段: id, uid, goods_id, addtime
      第二张表:商品表 goods
      字段: goods_id   goods_num
          方案1:  
      start transaction;
      select id from buy_record where uid=$uid and goods_id=$goods_id;
      if(结果不为空)
          抛异常,回滚。
      insert into buy_record。。。
      if(受影响行数<=0)
              抛异常,回滚。。。  
      select goods_num from goods where goods_id=$good_id;
      if(库存<=0)
              抛异常,回滚。。。  
      update goods set goods_num=goods_num-1 where goods_id=$goods_id;
      if(受影响行数<=0)
          该方法在高并发下几乎必然导致超卖。当库存为1的时候刚好多个用户同时    select goods_num from goods where goods_id=$good_id;此时库存刚好大于0,做update操作的时候必然减到小于0.  同时上面进行是否秒杀过的判重同样会出现类似问题  
          方案二:  
      start transaction;
          select id from buy_record where uid=$uid and goods_id=$goods_id          for       update        ;  
      if(结果不为空)
          抛异常,回滚。
      insert into buy_record。。。
      if(受影响行数<=0)
          抛异常,回滚。。。
          select goods_num from goods where goods_id=$good_id    for update    ;  
      if(库存<=0)
          抛异常,回滚。。。
          update goods set goods_num=goods_num-1     where goods_id=$goods_id    ;  
      if(受影响行数<=0)
          抛异常,回滚。。。
          该方法有效的防止了超卖,但是在每次select的时候加上了排它锁,每次select操作都会被堵塞    ,并发性能大大降低。  
                方案三:              对(uid,goods_id)加唯一索引!!      
      start transaction;
          insert into buy_record。。。  
      if(唯一索引报错?)
          抛异常,已经秒过了,回滚。。。
                update goods set goods_num=goods_num-1                         where goods_id=$goods_id          and                goods_num>0            ;      
      if(受影响行数<=0)
          抛异常,商品秒完了,回滚。。。
          该方法完美的解决了超卖与select排它锁导致的并发低的问题,并且4个sql缩减成2个sql语句。极大提升性能  

  • 相关阅读:
    DataTables合并单元格(rowspan)的实现思路(多分组分类的情况)
    DataTables固定表格宽度(设置横向滚动条)
    用图片替代cursor光标样式
    DataTables获取指定元素的行数据
    任意表格(table)实现拖动列(column)改变列大小
    鼠标拖动改变DIV等网页元素的大小的最佳实践
    DataTables实现rowspan思路
    DataTables添加额外的查询参数和删除columns等无用参数
    击穿(强推---神仙代码)
    java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结
  • 原文地址:https://www.cnblogs.com/Mryang-blog-cn/p/secondkill.html
Copyright © 2011-2022 走看看