当前位置:   article > 正文

thinkphp+redis实现超时取消订单功能_workerman 实现 订单关闭

workerman 实现 订单关闭

业务场景:秒杀案例

秒杀业务逻辑:多个用户同时抢单,通过mysql行锁抢到的用户进入待支付页面(倒计时)。当用户没有支付订单超时时则取消该订单并归还库存。

应用:

thinkphp+redis+workerman(可以自定义命令常驻)

1、thinkphp安装workerman。这里就过了,thinkphp手册去找。

2、安装好redis及扩展。用宝塔的直接搞就完了,过。

3、生产者:用户创建订单向redis插入一条订单数据。

  1. $redis = new \Redis();
  2. $redis->connect('127.0.0.1',6379);
  3. //$redis->auth('密码');//redis有密码就加
  4. /**
  5. *seckill_time为列队名称
  6. *time() + $seckill['pay_time']为到期时间戳
  7. *$newSeckillOrder->id为订单id,可以json字符串存储
  8. */
  9. $redis->zAdd('seckill_time', time() + $seckill['pay_time'], $newSeckillOrder->id);

4、消费者:这里我们需要一个常驻内存一直来查询这个列队是否有消息,如果有就消费掉。

workerman

  1. /**
  2. * 每个进程启动
  3. * @param $worker
  4. */
  5. public function onWorkerStart($worker)
  6. {
  7. //防止时间出问题
  8. date_default_timezone_set('PRC');
  9. $redis = new Redis();
  10. $redis->connect('127.0.0.1', 6379);
  11. //redis密码
  12. //$redis->auth('密码');//redis有密码就加此句
  13. if($worker->id === 0){
  14. //其他任务
  15. }
  16. //秒杀处理进程
  17. if($worker->id === 1){
  18. echo "启动秒杀任务!\n";
  19. //workerman定时器,每秒执行一次。
  20. Timer::add(1, function() use($redis) {
  21. //通过zRangeByScore查询seckill_time列队中0到当前时间戳的数据。
  22. $res = $redis->zRangeByScore('seckill_time', 0, time());
  23. //存在数据
  24. if (count($res) > 0) {
  25. foreach ($res as $k=>$v){
  26. //处理订单,$res[$k]为生产者存的订单id或数据。
  27. //.....
  28. //消费掉列队中的行数据
  29. $redis->zRem('seckill_time', $res[$k]);
  30. }
  31. //这步不用说都懂的吧!毕竟常驻内存,我们要管理好内存哦~
  32. unset($res);
  33. }
  34. });
  35. }
  36. }

测试结果:

cfcd743c36374210b56b928aaa70ccd4.png

 我这边是延迟20秒消费

如下:

f2a405d41d274673ab195397d97365b4.png

 消费掉后列队就空了哦~

使用该方案的原因:

可能有些人会问,workerman有定时器,可以直接延迟操作呀?为什么如此多此一举脱裤子放屁呢?

 

原因很简单,如果workerman突然出问题掉了,那定时器延迟的一些数据是不是就终止了呢?这样会导致丢掉的数据无法去关闭订单啦!所以采用redis延迟消息列队,将数据存入redis中,即使workerman出问题掉了,重新启动workerman也可以将没消费的数据消费掉!

关于redis重启丢数据问题需要修改配置如下。

  1. 找到appendonly no 改为 appendonly yes
  2. 找到appendfsync 设置为 appendfsync everysec

解决redis重启了就丢数据的问题。

当然也可以使用其他的消息中间件来解决,比如mq,不过对于宝塔用户安装简介还是redis吧!

记住!不要定时器循环查数据库判断!不要定时器循环查数据库判断!不要定时器循环查数据库判断!

说三遍,数据库压力很大的~

当然该方案也适用拼团到期自动关闭该团等,自行脑补。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/257614
推荐阅读
相关标签
  

闽ICP备14008679号