前言
在商品秒杀活动中,比如商品库存只有100,但是在抢购活动中可能有200人同时抢购,这样就出现了并发,在100件商品下单完成库存为0了还有可能继续下单成功,就出现了超卖。
实现原理
将商品库存从左侧循环lpush添加到num里,然后在下单的时候通过rpop每次从右侧弹出1件商品,当num的值为0时,停止下单。
代码
class Test extends BaseController
{
public $redis;
public function __construct(){
//初始化 连接redis
$this->redis = new \Redis();
$this->redis->connect('127.0.0.1',6379);
}
//连接redis
// redis-cli -h 127.0.0.1 -p 6379
//apache 模拟高并发 600次请求 每次请求500并发数
// ab -r -n 600 -c 500 https://******.cn/api/v1/test
/**
* 测试并发
*/
public function test()
{
$goods_id = 1;
// halt($this->redis->lrange('num',0,-1));
$goods = Db::name('redis_goods')->where('id',$goods_id)->find();
$count=$this->redis->rpop('num');//每次从num取出1
if($count == 0){
return "商品已被抢完了";
}
$uid = mt_rand(1000,9999);
$arr = [
'uid'=>$uid,
'create_at'=>microtime(),//毫秒时间戳
];
$res = Db::name('redis_data')->insert($arr);
Db::name('redis_goods')->where('id',$goods_id)->setDec('stock');
return "ok";
}
/**
* 将商品库存从左侧循环到lpush的num里
*/
public function ceshi(){
$goods_id = 1;
$goods = Db::name('redis_goods')->where('id',$goods_id)->find();
$num = $this->redis->llen('num');
$count = $goods['stock']-$num;
for ($i=1;$i<=$count;$i++){
//库存循环增加队列
$this->redis->lpush('num',1);
}
return "ok";
}
还不快抢沙发