主要原理
利用redis过期通知事件
1.redis配置
daemonize yes //守护进程
这里需要配置 notify-keyspace-events 的参数为 “Ex”。x 代表了过期事件
2.封装redis类
<?php
namespace app\common\service;
class MyRedis
{
private $redis;
public function __construct($host = '127.0.0.1', $port = 6379)
{
$this->redis = new \Redis();
$this->redis->connect($host, $port);
$this->setOption();
}
public function expire($key = null, $time = 0)
{
return $this->redis->expire($key, $time);
}
public function psubscribe($patterns = array(), $callback)
{
$this->redis->psubscribe($patterns, $callback);
}
public function setOption()
{
$this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
}
}
3.接受过期通知
这里用的是tp5的命令模式,框架如果支持命令模式会方便很多
<?php
#! /usr/local/php/bin/php
namespace app\api\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\model\Order;
use app\common\service\MyRedis;
class Test extends Command
{
protected function configure()
{
$this->setName('test')->setDescription('Here is the remark ');
}
protected function execute(Input $input, Output $output)
{
$redis = new MyRedis();
$redis->psubscribe(array('__keyevent@0__:expired'),
function ($redis, $pattern, $chan, $msg) use ($output) {
if ($pattern = '__keyevent@0__:expired' && $msg) {
$array = explode('_', $msg);
$function = $array['0'];
$this->$function($array['1']);
$output->writeln($msg);
}
});
}
/*
* 具体事件
*/
public function order($id)
{
$Order = Order::get($id);
$a=mt_rand(10000,99999);
$data['status'] = $a;
$Order->save($data);
}
}
4.把命令挂到后台一直去执行
nohup php /home/www/app/think test &
jobs #查看是否生效
ps aux | grep php #再看看也行
5.在需要的地方设置过期事件
setex order_1 5 chokingwin
然后就会自动触发order方法,参数是"_"后面的1
注意事项
如果代码修改过,记得kill掉 nohup,再启动一次
感谢chokingwin的文章
网友评论