tp5命令行+redis发布订阅实现定时任务

本文介绍了如何利用TP5框架结合Redis的发布订阅功能来实现定时任务。首先,安装Redis和phpredis扩展,然后创建自定义Redis类。接着,通过TP5的命令行工具创建命令,监听特定的Redis频道。当接收到“expired”键过期事件时,执行回调方法,通过curl调用接口执行业务逻辑。最后,通过Supervisor将PHP命令行任务设置为守护进程并实现开机自启,确保定时任务的稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到个这样的需求:点赞排行榜,在规定的时间内(可能有好几天),谁获赞多谁就获胜。今天试了下redis消息订阅,发现还可以,写写具体过程吧。

1.安装redis,phpredis扩展 

    这些网上一搜一大把

2.搜了个redis类,新建类:app\common\controller\MyRedis,代码如下:

<?php


namespace app\common\controller;


class MyRedis
{
    private $redis;

    public function __construct($host = '127.0.0.1', $port = 6379)
    {
        $this->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(没有的就新建),代码:

<?php

return [
    'app\index\command\Index',
];

   然后新建 application\index\command\Index.php,代码如下:

<?php

namespace app\index\command;

use app\common\controller\MyRedis;
use app\index\model\Teacher;
use think\console\Command;
use think\console\Input;
use think\console\Output;

class Index extends Command
{
    protected function configure()
    {
        $this->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持久化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值