Redis数据过期监听(发布/订阅模式,pub/sub)

Redis数据过期监听使用场景和延迟消息队列使用场景基本一致,例如订单失效、会员过期之类。
 
 
 
修改Redis配置文件并重启服务使之生效
[root@localhost ~]# vim /program/redis/redis.conf
#notify-keyspace-events ""
notify-keyspace-events "Ex" # 把notify-keyspace-events配置项的值设为Ex
[root@localhost ~]# service redis stop && service redis start
 
 
 
订阅者和发布者的代码非常简单,下面直接贴代码:
 
 
 
<?php
// +--------------------------------------------------------------+ //
// | 订阅者(相当于消息队列的消息消费者)                         | //
// +--------------------------------------------------------------+ //
declare(strict_types=1);
PHP_SAPI !== 'cli' && exit('脚本只能在命令行执行');
ini_set('display_errors', 'On');
error_reporting(-1);
set_time_limit(0);
ini_set('memory_limit', '-1');

function debug(string $text): void
{
    echo "[DEBUG] $text" . PHP_EOL;
}

function keyevent_expired_callback(mixed $redis, mixed $pattern, mixed $channel, mixed $key): void
{
    $redis instanceof Redis || debug('参数$redis类型异常');

    is_string($pattern) || debug('参数$pattern类型异常');

    is_string($channel) || debug('参数$channel类型异常');

    is_string($channel) || debug('参数$channel类型异常');

    // 重要提醒:使用KEY获取数据是获取不到的,因为这里是expired事件回调,数据早已过期了
    if (is_string($key)) {
        debug("数据($key)过期辣~~~");
    } else {
        debug('参数$key类型异常');
    }
}

$redis = new Redis();
$redis->connect('localhost');
$redis->auth('密码');
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

$dbNum = $redis->getDbNum(); // 获取数据库编号
$redis->psubscribe(["__keyevent@{$dbNum}__:expired"], 'keyevent_expired_callback');
// [DEBUG] 数据(name1)过期辣~~~
// [DEBUG] 数据(name2)过期辣~~~
// [DEBUG] 数据(name4)过期辣~~~
// [DEBUG] 数据(name6)过期辣~~~
// [DEBUG] 数据(name3)过期辣~~~

debug('这里是执行不到的,因为上面的Redis::psubscribe()方法会发生阻塞');


//========== 总结 ==========//
// 1、expired事件回调是数据过期后才触发的,所以在回调函数里无法获取原来的数据。
// 2、如果数据在过期前被删除了,那么该数据就不会再触发expired事件回调。


 
<?php
// +--------------------------------------------------------------+ //
// | 发布者(相当于消息队列的消息生产者)                         | //
// +--------------------------------------------------------------+ //
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);

$redis = new Redis();
$redis->connect('localhost');
$redis->auth('密码');

$redis->set('name1', '刘一', 1);
$redis->set('name2', '陈二', 2);
$redis->set('name3', '张三', 10); // 说明:该KEY有效期最长,所以会最后一个触发expired事件
$redis->set('name4', '李四', 4);
$redis->set('name5', '王五', 5); // 说明:该KEY后面会被删除,所以不会触发expired事件
$redis->set('name6', '赵六', 6);

$redis->del('name5');

Copyright © 2024 码农人生. All Rights Reserved