美文网首页技术方案秒杀专题其他零散知识点
高并发下库存扣减解决方案--分布式锁

高并发下库存扣减解决方案--分布式锁

作者: 小狼在IT | 来源:发表于2019-02-21 15:41 被阅读165次

    以下是个简单的库存扣减流程:


    image.png

    如果并发非常低的时候,基本就按这个流程走就行了。
    而这个设计,并发量稍大时,就会导致超卖的情况出现,两个同时要9台手机的请求,同时查到库存有12台,那操作下来,就会导致超卖:


    image.png

    嗯,那么出于职业道德,得加把锁:


    image.png

    嗯,这个设计,在高并发但库存量极少的秒杀场景,或者库存很高但并发量不高的(每秒10个请求),都是可行解。
    然而,这个相当于把程序串行化了。那么假设处理一个订单要200毫秒,在库存量很高(10万台),并发量极高(每秒1000个请求),有个请求就要等待200秒了,这个肯定不能接受的。

    解决办法:
    1.库存分段
    将10万库存,分成100段,每段1000个库存。对应的,就有100把锁去锁这100个库存段了,可以满足100个线程同时跑。


    image.png

    这套方案确实可以解决高并发,高库存问题,然而库存分段也是个麻烦的事。
    我这里还有个方案,虽然效率略低,但是跑起来应该还好。

    2.库存占用


    image.png

    把串行化的步骤,改成了只是简单地往“库存占用表”插入数据即可,耗费的时间是低的,可以应付较高的并发量。

    实现方式:

    public static void main(String[] args) {
    
        try{
            Config config = new Config();
            config.useSingleServer().setAddress("redis://127.0.0.1:6222");
            config.useSingleServer().setPassword("test");
            RedissonClient  finalRedisson = Redisson.create(config);
            //需求数量
            int requireQty = 9;
            for(int i=0;i<30;i++){
                Thread t = new Thread(()->{
                    try{
    
                        RLock rLock = finalRedisson.getLock("myLock");
                        System.out.println(Thread.currentThread().getName()+ "开始");
                        RAtomicLong stockQty = finalRedisson.getAtomicLong("stockQty");
                        RAtomicLong stockOccupy = finalRedisson.getAtomicLong("stockOccupy");
                        rLock.lock();
                        long l1 = stockQty.get();
                        long l2 = stockOccupy.get();
                        long l = l1 - l2;
                        System.out.println(Thread.currentThread().getName() + "获得锁");
                        System.out.println(Thread.currentThread().getName() + "do something");
                        if(l >= requireQty) {
                            stockOccupy.set(stockOccupy.get()+requireQty);
                        }
                        rLock.unlock();
                        //创建订单,扣减库存
                        Thread.sleep(200);
                        if(l >= requireQty) {
                            System.out.println(Thread.currentThread().getName() + "done,库存剩下:" + l);
                        }
                        else {
                            System.out.println(Thread.currentThread().getName() + "库存不足,库存剩下:" + l);
                        }
                       // System.out.println(Thread.currentThread().getName() + "准备释放锁");
                        System.out.println(Thread.currentThread().getName() + "结束");
                    }
                    catch (Exception ex){
                        System.out.println(ex.getMessage());
                    }
    
                });
                t.start();
            }
        }
        catch (Exception ex){
            System.out.println(ex.getMessage());
        }
        finally {
    
        }
    
    }
    

    执行前:


    image.png
    image.png

    执行后:


    image.png

    部分执行结果:


    image.png

    剩下1个库存的时候,就跑步下去了。

    相关文章

      网友评论

        本文标题:高并发下库存扣减解决方案--分布式锁

        本文链接:https://www.haomeiwen.com/subject/qhuryqtx.html