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 ?>