最近遇到个这样的需求:点赞排行榜,在规定的时间内(可能有好几天),谁获赞多谁就获胜。今天试了下redis消息订阅,发现还可以,写写具体过程吧。
1.安装redis,phpredis扩展
这些网上一搜一大把
2.搜了个redis类,新建类:app\common\controller\MyRedis,代码如下:
redis = new \Redis();
$this->redis->config('notify-keyspace-events','Ex');//开启redis key 过期通知(改过配置文件,但没成功)
$this->redis->connect($host, $port);
}
public function setex($key, $time, $val)
{
return $this->redis->setex($key, $time, $val);
}
public function set($key, $val)
{
return $this->redis->set($key, $val);
}
public function get($key)
{
return $this->redis->get($key);
}
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 subscribe($patterns = array(), $callback)
{
$this->redis->subscribe($patterns, $callback);
}
public function setOption()
{
$this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
}
}
注意看我代码注释那句:
3.使用tp5命令行
在application下新建文件command.php(没有的就新建),代码:
然后新建 application\index\command\Index.php,代码如下:
setName('hello')
->setDescription('Say Hello world');
}
protected function execute(Input $input, Output $output)
{
$redis = new MyRedis();
$redis->setOption();
$redis->psubscribe(array('__keyevent@0__:expired'), function ($redis, $pattern, $chan, $msg){
// echo $msg.' ';
// $teacher = new Teacher();
// $teacher->name = $msg;
// $teacher->save();
var_dump($redis,$pattern,$chan,$msg);
});
}
}
建了一个 “hello”命令,重点是execute()方法,redis的psubscribe监听 “0”这个数据库,有 key "expired"(过期)就执行后面的回调方法,在回调方法里可以使用curl方式调用写好的接口,功能逻辑有变动也不需要修改这里命令行的代码,$msg参数就是过期的键名,在我这里就应该是存放的是某个项目的id。
4.执行
在项目根目录,先php think查看是有已有“hello”这个命令,
然后执行hello命令
现在就在“监听”有没有过期的key了,有的话会打印出来:
5.完善
1)使用supervisor将"php think hello"命令加入守护命令,并将supervisor设置开机自启
安装supervisor。。。
在supervisor配置文件supervisord.conf末尾,有这样一句话
[include]
files = supervisord.d/*.conf
在对应路径下,新建自己的配置文件 hello.conf,其内容如下:
[program:hello]
command=/usr/bin/php /usr/html/php/think hello
process_name=%(program_name)s_%(process_num)02d
;numprocs=5
autostart=true
autorestart=true
startsecs=1 ;程序重启时候停留在runing状态的秒数
startretries=10 ;启动失败时的最多重试次数
redirect_stderr=true
user=root
stdout_logfile=/etc/supervisord.d/challenge.log
[supervisord]
[supervisorctl]
注意:command, /usr/bin/php是php运行文件,/usr/html/php/是tp项目根目录,后面think hello就是创建的tp命令行,所以这句话的意思就是执行 php think hello
stdout_logfile 是日志、echo var_dump等输出的地方
另外,每次改动命令行相关代码,都需要重新加载supervisor。
2)redis持久化