PHP + Redis实现自动取消订单

  • 业务场景
  • Redis 开启 keyspace notifications
  • tp5.1 代码实现
  • 后台运行脚本

  简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件)
  需要注意此功能是在 redis 2.8版本以后推出的,因此你服务器上的 reids 最少要是 2.8 版本以上

业务场景

当一个业务触发以后需要启动一个定时任务,在指定时间内再去执行一个任务(如自动取消订单,自动完成订单等功能)
Redis 的 keyspace notifications 会在 key 失效后发送一个事件,监听此事件的的客户端就可以收到通知

Redis 开启 keyspace notifications

redis 默认不会开启 keyspace notifications,因为开启后会对cpu有消耗

  • 更改Redis配置文件(redis.conf)
# 原配置:
notify-keyspace-events ""# 更改为:
notify-keyspace-events "Ex"
  • 重启 Redis,查看 notify-keyspace-events 的值是不是 xE
# redis-cli 命令行# 查看redis配置信息
config get *# 监听key过期事件
# keyevent 事件,事件以 __keyevent@<db>__ 为前缀进行发布
# expired 过期事件,当某个键过期并删除时会产生该事件
psubscribe __keyevent@0__:expired

tp5.1 代码实现

  • 创建自定义指令
    创建一个自定义命令类文件,新建 application/common/command/Timeout.php
<?phpnamespace app\command;use app\common\model\Order;
use app\facade\Cache;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use think\Exception;class Timeout extends Command
{protected function configure(){parent::configure(); // TODO: Change the autogenerated stub$this->setName('timeout')->setDescription('Cancel Timeout Order');}protected function execute(Input $input, Output $output){$this->getKey();$output->writeln("ok");}public function getKey() {// socket流的超时时间 -1禁用超时ini_set('default_socket_timeout', -1);// cli模式下,开启数据库断开重连,防止脚本运行一段时间后数据库断开连接$dbConfig = config('database.');$dbConfig['break_reconnect'] = true;Db::init($dbConfig);// 返回Redis句柄对象$redis = Cache::store('redis')->handler();// Redis 订阅监听过期事件$redis->psubscribe(array('__keyevent@0__:expired'), 'app\command\Timeout::keyCallback'); // 回调必须写绝对路径 要不然会报错}// key过期回调public static function keyCallback($redis, $pattern, $channel, $message) {// redis key 示例: course_order=6434@@2021071116061353484856if (strpos($message, 'course_order=') !== false) {$str = substr($message, strlen('course_order='));list($orderId, $orderNo) = explode('@@', $str);// 自动取消课程报名订单(更新订单状态)try {$status = Order::where(['id' => $orderId])->value('status');// 未付款if ($status == 0) {$res = Order::where(['id'=> $orderId])->update(['status'=>2]);$scriptMsg = '';$logMsg = '';if ($res) {$scriptMsg .= "success update order, order_id:$orderId order_number:$orderNo. ";$logMsg .= "=====success order表更新成功: 订单id:$orderId, 订单编号:$orderNo=====";} else {$scriptMsg .= "error update order, order_id:$orderId order_number:$orderNo. ";$logMsg .= "-----error order表更新失败: 订单id:$orderId, 订单编号:$orderNo-----";}self::timeoutOrderWriteLog($logMsg); // 写入日志echo $scriptMsg; // 脚本消息提示}} catch (Exception $e) {self::timeoutOrderWriteLog('Error: 自动取消订单异常, 异常信息:' . $e->getMessage());//throw new Exception($e->getMessage());}}}/*** 取消订单写入日志* @param string $data 写入的信息*/public static function timeoutOrderWriteLog($data){//设置路径目录信息$datefile = date('Ym');$url = './log/'.$datefile.'/timeout-order.txt'; // 项目根目录,而非public目录$dir_name=dirname($url);//目录不存在就创建if(!file_exists($dir_name)){//iconv防止中文名乱码$res = mkdir(iconv("UTF-8", "GBK", $dir_name),0777,true);}$fp = fopen($url,"a");//打开文件资源通道 不存在则自动创建fwrite($fp,date("Y-m-d H:i:s").var_export($data,true)."\r\n");//写入文件fclose($fp);//关闭资源通道}
}
  • 配置 application/command.php 文件
return ['app\command\Timeout' // 超时自动取消订单
];
  • 测试-命令帮助-命令行下运行
php think

输出:

  • 运行 timeout 命令
php think timeout# 输出
ok

后台运行脚本

使用 & 命令,后台运行脚本,并使用定时任务每隔一分钟去检查进程是否还存在,没有则重新启动该脚本

  • 后台运行脚本
setsid php think timeout > /opt/nginx/tp5.1/log/nohup.txt & # 后台运行脚本
  • 安装 crontab
yum install -y vixie-cron
  • 项目根目录新建 monitor.sh 脚本文件,并写入以下内容
#!/bin/bash
alive=`ps aux|grep "php think timeout"|grep -v grep|wc -l`
if [ $alive -eq 0 ]
then
cd /opt/nginx/tp5.1
php think timeout > /opt/nginx/tp5.1/log/nohup.txt &
fi
  • 添加计划任务(每分钟检测一次)
crontab -e* * * * * /opt/nginx/tp5.1/monitor.sh > /dev/null &

部署完毕后,对于超时的订单系统将自动取消,并写入日志到 /log/日期文件夹/timeout-order.txt 文件中

tp5.1 PHP + Redis实现自动取消订单相关推荐

  1. 使用PHP+Redis实现延迟任务,实现自动取消订单功能

    简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件) 需要注意此功能是在redis 2.8版本以后推出的,因此你服务器上的reids最少要是2.8版本 ...

  2. php redis zset 延迟队列_用PHP+Redis实现延迟任务,实现自动取消订单

    简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件) 需要注意此功能是在redis 2.8版本以后推出的,因此你服务器上的reids最少要是2.8版本 ...

  3. PHP+Redis实现延迟任务 实现自动取消订单,自动完成订单

    简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件) 需要注意此功能是在redis 2.8版本以后推出的,因此你服务器上的reids最少要是2.8版本 ...

  4. 秒杀情况下,用户下单扣除库存创建订单之后,迟迟不付款,时间到了自动取消订单(思路)

    秒杀情况下,用户下单扣除库存创建订单之后,迟迟不付款,时间到了自动取消订单 解决方案1. 使用redis实现 1.下单之后把生成分布式全局唯一id,把订单id放进redis中,设置一个过期时间 2.定 ...

  5. Laravel自动取消订单

    最近的业务需要做15分钟内未完成支付就自动取消订单的功能,类似的功能还有很多,例如:订单完成后自动确认收货.完成付款5分钟后发送短信通知等等,这些看起来就像定时任务,即多久后去做什么事. 实现上述功能 ...

  6. 三小时未付款自动取消订单实现

    电商系统中,有这样的需求,用户下单三小时未支付就自动取消,具体如何实现的呢? 一.实现方案 通常实现方案有以下方式: 方式一 使用定时任务不断轮询取消,此种方式实现简单,但是存在一个问题,定时任务设置 ...

  7. 虾皮系统老出现服务器错误,Shopee卖家须知:虾皮系统什么状况会自动取消订单?...

    系统自动取消订单 虾皮系统什么状况会自动取消订单? ● 对卖家而言 以下三种状况,虾皮系统会自动取消订单: 1.卖家在设定的出货天数内,未申请超商寄件编号或是黑猫取件,系统将于该出货天数的隔天自动取消 ...

  8. php 超时支付取消订单,php利用workerman的定时器实现延时操作(订单支付不成功后一定时间未支付自动取消订单)...

    延时操作个人目前接触最多的场景是用户下单后一定时间未支付自动取消订单,传统的做法是采用定时任务定时扫描数据库超时订单或者利用客户端的请求每次请求去检测一次是否有超时订单,这些方法我始终感觉不是很好,所 ...

  9. springboot整合RabbitMQ实现延时自动取消订单

    1.pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>s ...

最新文章

  1. PHP获取客户端的网卡mac物理地址
  2. java基础提升篇:深入剖析Java中的装箱和拆箱
  3. 【Linux网络编程】并发服务器之多进程模型
  4. redis日志追加频率
  5. python实现小型搜索引擎设计_基于JAVA的中小型饭店餐饮管理系统的设计与实现...
  6. 5000字权威指南分享!企业如何正确制定 IT 战略及其路线图
  7. 抗击肺炎,中国互联网公司在行动
  8. 大数据学习笔记:HBase Shell操作
  9. 计算机专业大学排名_最新!2020美国九大热门专业最具薪资潜力大学排名来了!...
  10. java实现ftp文件上传失败_用java+ftp实现文件上传的问题?
  11. html字体样式不显示不出来,css怎么设置不显示文字
  12. 2020国内可用的android镜像网站
  13. OSI七层模型和STP/IP协议模型(生动形象,简单易懂)
  14. 数据结构与算法精选面试50题(附答案)
  15. vs2017 fatal error LNK1104: 无法打开文件“\.obj”
  16. 运行JS代码报错:Uncaught TypeError: Cannot read property‘style‘ of undefined
  17. 期货开户的身份识别验证
  18. 读书笔记--推荐系统实践 第一章
  19. RSD 99脚本语言拼接屏幕墙实像元显示程序剖析
  20. 多策略融合改进的均衡优化算法

热门文章

  1. access数据库导入oracle数据库,将excel表格导入access数据库再导入oracle数据库方法-如何将ACCESS数据库的文件导入到ORACLE中?...
  2. 遥感水文前景_黑河流域中游地区生态水文过程及其分布式模拟
  3. lane是什么意思_您知道lane是什么意思吗?
  4. 【python爬虫】 爬取ip代理池
  5. “筑爱助残 亲近自然”与残友一起户外活动
  6. [笔记]Windows使用OpenVpn构建虚拟局域网
  7. 图解人工智能发展史和人工智能全景图
  8. 虚拟机连接网络的图标不见了
  9. 贵州:“区块链+”促经济转型产业升级
  10. CentOS7安装Scrot