php监听redis key失效触发回调事件(订阅消息)

3 篇文章 0 订阅

今天程序要实现一个功能 就是 一个答疑系统 学员提出问题 然后老师回答问题 如果两个小时后 老师没有回答问题 就提醒助教来回答问题

然后问题就出在这里 怎么能实现 如果学员提出问题 老师没有回答 怎么在两个小时后 提醒助教

最开始的想法 就是 定时任务 扫表

用mysql 查回答状态为没回答的

写个php脚本 while true ,没查到就sleep 2 查到就处理 每次查询加limit 一次10条

或者使用 crontab 一分钟一次也行

然后我们决定使用redis 的key失效的时候 来 触发一个回调事件

下面是我做这个功能的记录

第一步 是修改redis的配置文件

Key过期事件的Redis配置
这里需要修改redis的配置的文件,配置 notify-keyspace-events 的参数为 “Ex”。x 代表了过期事件。notify-keyspace-events “Ex” 保存配置后,重启Redis服务,使配置生效。

先开启一个redis-cli客服端,订阅所有操作,等待接收消息

Psubscribe keyevent@0:expired

在这里插入图片描述

2.再开启一个终端,redis-cli 进入 redis,新增一个 10秒过期的键

在这里插入图片描述

10秒过期后,接收到的消息如下:

在这里插入图片描述

如果这个时候 消息 接收到了 就证明 配置没有问题了

接下来 就是写代码
第一步

设置过期事件:index.php

1.	require_once './Redis.class.php';
2.	$redis = new \Redis();
3.	$order_id = 123;
4.	$redis->setex('order_id',10,$order_id);

过期事件的订阅:psubscribe.php

1.	require_once './Redis.class.php';
2.	$redis = new \Redis();
3.	// 解决Redis客户端订阅时候超时情况
4.	$redis->setOption();
5.	$redis->psubscribe(array('__keyevent@0__:expired'), 'keyCallback');
6.	// 回调函数,这里写处理逻辑
7.	function keyCallback($redis, $pattern, $chan, $msg)
8.	{
9.	    echo "Pattern: $pattern\n";
10.	    echo "Channel: $chan\n";
11.	    echo "Payload: $msg\n\n";
12.	}

先用命令行模式执行 psubscribe.php

在浏览器访问
http://localhost/index.php
(这里是我的路径,具体可以改成你自己的路径)
命令行窗口就会有如下信息输出:

这就是一个正常的流程

接下来是我遇到的一些问题

  1. 另外,每次改动命令行相关代码,都需要重新加载supervisor。

当我执行订阅消息 psubscribe.php 窗口开着的时候 进程是在的 窗口关了 进程就不在了

这个时候 就要 加在一个命令的最前面,表示不挂断的运行命令

  1. 后台执行
    一般运行linux上的程序都是执行 .sh 文件(./sh文件),那如果不影响当前CMD窗口的操作,需要后台运行怎么办呢?
    这时就需要借助 nohup 和 & 命令来实现。

(1) nohup
加在一个命令的最前面,表示不挂断的运行命令
(2) &
加载一个命令的最后面,表示这个命令放在后台执行

还有一个问题

解决phpredis ‘RedisException’ with message ‘read error on connection’

最近一个后台常驻job通过redis的brpop阻塞读取消息时,设置的超时时间较长
list( k e y , key, key,row)= r e d i s − > b r P o p ( redis->brPop( redis>brPop(queue_name,3600); //超时时间为1小时
但是在实际的使用中发现很短时间后就会退出,通过查看error log,发现:‘RedisException’ with message ‘read error on connection’ 提示
经过一番折腾,原来发现是php.ini文件中的一个配置项导致:
default_socket_timeout = 60
由于redis扩展也是基于php 的socket方式实现,因此该参数值同样会起作用。
找到了问题就比较好解决了:
1、直接修改php.ini,将其设置为我们想要的值(这个不推荐)
2、在我们的脚本中通过以下方式设置,这样就比较灵活,不对其他脚本产生影响

ini_set('default_socket_timeout', -1);  //不超时
public function psubscribe(){
        ini_set('default_socket_timeout', -1);
        $redis=new \Redis();
        $redis->connect('127.0.0.1',6379);
        $redis->setOption();
        $redis->psubscribe(array('__keyevent@0__:expired'), function($redis, $pattern, $chan, $msg){
		//这里可以写要执行的操作
           	echo 123;
    }

这里是 执行监听订阅消息

在这里插入图片描述
在这里插入图片描述

这里就能看到 这个监听了

这个时候设置一个key有到期时间 时间到了 就会触发这个方法 触发里面的回调方法
回调方法里面的 $msg 就是到期的key 获取到key 就可以操作了

备注:
使用了一段时间因为我的回调函数里面有查数据库 发现启动后是好使的 过了一段时间就查数据库为空 上网查是说 mysql连接默认是8小时 过了8小时 就连接不上了
网上说
其中的mysql_ping()用来判断连接是否已经被断开了,若是断开了,关闭当前的链接,重新创建新的连接.
这样,只要发现连接被断开了,即可重新连接了.

function reconnect(){
if (!mysql_ping ($this->db)) {
//here is the major trick, you have to close the connection (even though its not currently working) for it to recreate properly.
mysql_close($this->db);
$this->connect();
}
}

thinkphp5的话
tp5 旧版本的bug (5.0.16 以下的版本存在) 使用新版本可以解决。

database.php 配置文件中

加入断线重连,可以解决

//断线重连
'break_reconnect' => true,

我现在是直接在回调函数里面写的pdo连接数据库,还在测试

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunsijia21983

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值