zoukankan      html  css  js  c++  java
  • 如何解决高并发秒杀的超卖问题

    如何解决高并发秒杀的超卖问题
     
    由秒杀引发的一个问题
    • 秒杀最大的一个问题就是解决超卖的问题。其中一种解决超卖如下方式:
    1 update goods set num = num - 1 WHERE id = 1001 and num > 0
     
    我们假设现在商品只剩下一件了,此时数据库中 num = 1;
     
    但有100个线程同时读取到了这个 num = 1,所以100个线程都开始减库存了。
     
    但你会最终会发觉,其实只有一个线程减库存成功,其他99个线程全部失败。
     
    为何?
     
    这就是MySQL中的排他锁起了作用。
     
    排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
    就是类似于我在执行update操作的时候,这一行是一个事务(默认加了排他锁)。这一行不能被任何其他线程修改和读写
     
     
    • 第二种解决超卖的方式如下
     
    1 select version from goods WHERE id= 1001
    2 update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version);
     
    这种方式采用了版本号的方式,其实也就是CAS的原理。
     
    假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。
     
    然后直接update的时候,只有其中一个先update了,同时更新了版本号。
     
    那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了。那么我就放弃这次update
     
    • 第三种解决超卖的方式如下
     利用redis的单线程预减库存。比如商品有100件。那么我在redis存储一个k,v。例如 <gs1001, 100>
     
    每一个用户线程进来,key值就减1,等减到0的时候,全部拒绝剩下的请求。
     
    那么也就是只有100个线程会进入到后续操作。所以一定不会出现超卖的现象
     
    • 总结
     
    可见第二种CAS是失败重试,并无加锁。应该比第一种加锁效率要高很多。类似于Java中的Synchronize和CAS
     
  • 相关阅读:
    C语言得到当前系统时间
    【solr这四个主题】在Tomcat 部署Solr4.x
    MySQL 一般查询日志(General Query Log)
    iOS7 UIKit动力学-碰撞特性UICollisionBehavior 上
    Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成
    Kaggle入门——使用scikit-learn解决DigitRecognition问题
    Effective C++:规定34:区分接口继承和实现继承
    Critical thinking and Thoughtful writing
    我的时间,GTD做主
    jquery自己主动旋转的登录界面的背景代码登录页背景图
  • 原文地址:https://www.cnblogs.com/wenbochang/p/10912459.html
Copyright © 2011-2022 走看看