当我们的平台上的用户下了订单,但是没有付款时,我们一般会给这个订单保存 两个小时的时间 ,两小时过后,就要对这个订单进行做废处理,把订单上的商品的库存 归还
有两种方法来实现,
一.服务器的定时任务 crontab
这种方式的缺点,就是时间不是那么准确,如果要两个小时定单过期,我的方法是让定时任务 一个小时执行一次,对全部未付款的订单进行查找,并设置过期,用foreach循环来返还库存
二.就是使用redis的发布订阅机制
这个方法可以做到时间准确, 而且是一条一条的数据修改
这里主要说第二种方法
它主要是用了redis的发布订阅机制, redis的notify-keyspace-events 会自动发布一个频道 频道的名称有固定的格式,这里我们监听 键的失效事件 的订阅频道名是 __keyevent@0__:expired 订阅了这个频道,当redis的 第0号数据库中有键名失效时,就会收到一个推送,我们就利用这个特点来完成功能
首先,安装redis,
配置:这果在 redis.conf中 设置监听,键的失效事件 notify-keyspace-events Ex
配置好后,重启redis的服务端
代码如下:
我们先写一个订阅频道 的文件,这个文件要在命令行执行,并且是一个阻塞式的 文件名:subscribe.php
<?php
ini_set('default_socket_timeout', -1); //这一句是说长连接不超时,如果没有的话,这个文件会在运行一段时间后自动停止,一定不能少
$redis = new \Redis();
$redis->connect("127.0.0.1",6379);
$redis->subscribe(["__keyevent@0__:expired"],function($a,$b,$c){
var_dump($a,$b,$c);
var_dump($c);
});
这里只是大至代码,在 function($a,$b,$c)的函数体中,就可以写上订单作废的逻辑,还有返还库存的逻辑,$a ,$b ,$c是 phpredis自动会给我们加上的参数, $a 是一个redis对象,$b是事件的名称,也就是 __keyevent@0__:expired ,$c 就是失效的键的名称,我们可以用 生成的订单号做会键名,那么它就是要作废的 订单号,我们就可以用它来做逻辑操作了
在我们的下订单的程序中就可以这样写了
伪代码,
$redis = new \redis();
$redis->connect(”127.0.0.1“,6379);
$redis->setex("order_420682198105122517",60*60*2,"任意的值,没多大用");
当我们的订单在两个小时没有支付时,就会触发 subscribe.php 中的function($a,$b,$c) 函数,此时 $c=order_420682198105122517, 有了订单号后面的逻辑就不是问题了