常规的秒杀处理逻辑(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 ?>

 

posted @ 2020-08-27 11:24  rianley  阅读(556)  评论(0编辑  收藏  举报