常规的秒杀处理逻辑(php)
1 ## 初始化抢购数据 2 <?php 3 4 // 假设当前秒杀活动的 id 为 9 5 // 可以在模型的 created 事件做这个事情 6 $id = 9; 7 8 // 填充一个 redis 队列,数量为抢购的数量,后面的 9 无意义 9 \Redis::lpush("seckills:{$id}:queue", array_fill(0, $seckill->number, 9)); 10 11 ?> 12 13 ## 抢购 14 <?php 15 16 // 从路由或者参数中得到当前秒杀活动的 id 17 $id = 9; 18 $userId = auth()->id(); 19 20 // 判断是否已经开始了秒杀 21 22 // 返回 0,代表当前用户已经抢购过了 23 if (0 == Redis::hset("seckills:{$id}:users:{$userId}", 'id', $userId)) { 24 25 return responseJson(403, '你已经抢购过了'); 26 } 27 28 // 如果从队列中读取到了 null,代表已经没有库存 29 if (is_null(Redis::lpop("seckills:{$id}:queue"))) { 30 31 return responseJson(403, '已经抢购完了'); 32 } 33 34 // 这里就可以开始入库订单 35 36 ?> 37 38 ## 利用 crontab 定时扫描过期数据,回滚库存,删除过期 redis (可选) 39 <?php 40 41 // 查出已经过期确没有回滚过的秒杀, 42 Seckill::query() 43 ->where('end_at', '<', date('Y-m-d H:i:s')) 44 ->get() 45 ->map(function (Seckill $seckill) { 46 47 // 先模糊查找到所有用户 key 48 $ids = Redis::keys("seckills:{$seckill->id}:*"); 49 Redis::del($ids); 50 51 // 回滚库存 52 // 做更多的事 53 }; 54 55 ?>