Redis防止超卖的两种实现

2020-08-12  本文已影响0人  莴牛

环境准备:mac,php7,redis,laravel

新建个数据库表用来测试

CREATE TABLE `goods_sold` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `goods_id` bigint(20) DEFAULT NULL,
  `num` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

#插入一条数据
INSERT INTO `goods_sold` (`goods_id`, `num`) VALUES (1, 100);
  public function OverSoldFunctionWithRedisTransaction()
  {
        // todo 从数据库获取库存 这里忽略,直接写死一个 提前取出放入缓存中
        $total = 100;

        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);

        $key = 'watchKey';
        $watchKey = $redis->get($key);
        if ($watchKey < $total) {
            $redis->watch($key);

            // 开启redis事务
            $redis->multi();
//            sleep(1);

            $redis->set($key, $watchKey + 1);
            $transResult = $redis->exec();

            if ($transResult) {
                GoodsSold::find(1)->decrement('num');
                exit('抢购成功');
            } else {
                exit('抢购失败,下次再来');
            }
        } else {
            exit('商品已抢光');
        }
    }

ab压测看实际效果

ab -n 1000 -c 100 -k http://laravel.tyl.com/over/sold
压测数据
redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> get watchKey
"100"
127.0.0.1:6379> del watchKey
(integer) 1
127.0.0.1:6379> get watchKey
(nil)
127.0.0.1:6379>
    #先使用第一步取出库存放入队列中
    /**
     * 取出库存放入队列中
     */
    public function PushQueue()
    {
        $data = GoodsSold::find(1);
        $total = $data->num;
        if ($total > 0) {
            $redis = new \Redis();
            $redis->connect('127.0.0.1', 6379);

            $queueKey = 'queueKey';
            for ($i = 1; $i <= $total; $i++) {
                $redis->lPush($queueKey, $i);
            }
        }
    }

    /**
     * 超卖实现二
     */
    public function OverSoldFunctionWithRedisQueue()
    {
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);

        $queueKey = 'queueKey';

        if ($redis->rPop($queueKey)) {
            GoodsSold::find(1)->decrement('num');
            exit('抢购成功');
        } else {
            exit('商品已抢光');
        }
    }

ab压测看实际效果

ab -n 1000 -c 100 -k http://laravel.tyl.com/over/sold/2

总结

上一篇下一篇

猜你喜欢

热点阅读