跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

phpEnv怎么配置Redis的过期Key回调通知?

必须在Redis服务端配置notify-keyspace-events Ex并重启服务,PHP用psubscribe('__keyevent@*__:expired')监听,回调中不可调用Redis命令,需通过消息队列或子进程处理业务逻辑。 phpEnv 环境下无法直接通过 php.ini 或 Apache/Nginx 配置启用 Redis 过期回调 —— 因为该功能完全依赖 Redis 服务端的
notify-keyspace-events
设置,与 PHP 运行环境无关。 你得先改 Redis 本身,再让 PHP 客户端正确订阅,否则
psubscribe
永远收不到消息。 必须在 Redis 服务端开启
notify-keyspace-events Ex
phpEnv 自带的 Redis(通常是 Windows 版或精简版)默认关闭键空间通知,且配置文件位置不统一。常见路径有:
C:\phpEnv\redis\redis.conf
或
C:\phpEnv\RedisServer\redis.windows.conf
。打开后查找:
notify-keyspace-events ""
将其改为:
notify-keyspace-events Ex
注意:
Ex
中的
E
表示“键事件通知”(前缀
__keyevent@*
),
x
表示“过期事件”,二者缺一不可。只写
x
无效;写
Kx
也可用,但 PHP 订阅时需对应改频道名。 立即学习 “ PHP免费学习笔记(深入) ”; 改完必须重启 Redis 服务(不是重启 phpEnv,而是单独重启
RedisServer.exe
或服务项),否则配置不生效。 PHP 代码里只能用
psubscribe
,不能用
subscribe
因为过期事件是广播式、模式匹配的,必须用模式订阅(pattern subscribe)。常见错误是写成: PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载
$redis->subscribe(['__keyevent@0__:expired'], $callback); // ❌ 错:这是精确订阅,收不到
正确写法是:
$redis->psubscribe(['__keyevent@*__:expired'], function ($redis, $pattern, $channel, $msg) {
echo "过期 key: {$msg}\n"; // $msg 就是 key 名
});
__keyevent@*__:expired
中的
*
表示监听所有数据库(db0–db15),避免因业务写到非 0 库而漏事件 回调函数第四个参数
$msg
是纯 key 名字符串,不是 JSON 或完整消息体 该连接会一直阻塞等待,必须运行在常驻进程(如 CLI 脚本)中,Web 请求里调用会超时
psubscribe
回调内禁止调用
$redis
的其他命令 这是最隐蔽的坑:在
psubscribe
的回调闭包里执行
$redis->get($msg)
或
$redis->del($msg)
会直接报错或静默失败,典型现象是:
Warning: Redis::get(): read error on connection in ...
原因:Redis Pub/Sub 连接处于特殊状态,不支持混用命令。解决方案只有两个: 把要操作的 key 名(即
$msg
)通过消息队列(如 Beanstalkd、Redis List)转给另一个独立 worker 进程处理 或用
pcntl_fork()
派生子进程,在子进程中新建
Redis
实例去操作 —— 但要注意资源泄漏和僵尸进程回收 别试图在回调里重连 Redis,它不会解决根本限制。 验证是否生效,别只信日志 光看 PHP 是否打印出 key 名不够,得确认三件事都通: Redis 日志里有类似
127.0.0.1:6379> CONFIG GET notify-keyspace-events
返回
["notify-keyspace-events","Ex"]
用
redis-cli --csv psubscribe '__keyevent@*__:expired'
在终端手动监听,然后
SET testkey 123 EX 2
,2 秒后应立刻收到一行
"pmessage","__keyevent@*__:expired","__keyevent@0__:expired","testkey"
PHP 脚本用
php listen.php
启动后,同样
SET
测试 key,观察是否输出 只要其中一环断掉,整个链路就失效 —— 而最容易被忽略的是:phpEnv 的 Redis 服务没真正重启,或者配置改在了错误的 .conf 文件里。

相关文章