背景
最近需要涉及一個定時通知的業務,之前的辦法是采用定時任務,每秒查詢一次。后來了解到Redis的鍵空間通知機制,其中的過期通知,和業務非常貼合。
鍵空間通知
下面是Redis中文文檔的介紹
鍵空間通知使得客戶端可以通過訂閱頻道或模式, 來接收那些以某種方式改動了 Redis 數據集的事件。事件通過 Redis 的訂閱與發布功能(pub/sub)來進行分發, 因此所有支持訂閱與發布功能的客戶端都可以在無須做任何修改的情況下, 直接使用鍵空間通知功能。
事件類型
對於每個修改數據庫的操作,鍵空間通知都會發送兩種不同類型的事件。
比如說,對 0 號數據庫的鍵 mykey 執行 DEL 命令時, 系統將分發兩條消息, 相當於執行以下兩個 PUBLISH 命令:
PUBLISH keyspace@0:mykey del
PUBLISH keyevent@0:del mykey
訂閱第一個頻道 keyspace@0:mykey 可以接收 0 號數據庫中所有修改鍵 mykey 的事件, 而訂閱第二個頻道 keyevent@0:del 則可以接收 0 號數據庫中所有執行 del 命令的鍵。
以 keyspace 為前綴的頻道被稱為鍵空間通知(key-space notification), 而以 keyevent 為前綴的頻道則被稱為鍵事件通知(key-event notification)。
當 del mykey 命令執行時:
鍵空間頻道的訂閱者將接收到被執行的事件的名字,在這個例子中,就是 del 。
鍵事件頻道的訂閱者將接收到被執行事件的鍵的名字,在這個例子中,就是 mykey 。
配置
另外開啟Redis的鍵空間通知,需要修改配置文件。查看默認的配置你會發現“notify-keyspace-events”字段,且為空,表示不開啟。總共有以下這幾種設置:
字符 發送的通知
K 鍵空間通知,所有通知以 keyspace@
E 鍵事件通知,所有通知以 keyevent@
g DEL 、 EXPIRE 、 RENAME 等類型無關的通用命令的通知
$ 字符串命令的通知
l 列表命令的通知
s 集合命令的通知
h 哈希命令的通知
z 有序集合命令的通知
x 過期事件:每當有過期鍵被刪除時發送
e 驅逐(evict)事件:每當有鍵因為 maxmemory 政策而被刪除時發送
A 參數 g$lshzxe 的別名
其中必選K或E,比如開啟過期通知,“Ex”或者"Kx",兩者的區別在於事件名不同,不過我們可以采用模糊訂閱的方式,如果開啟所有事件則是“AKE”
訂閱
訂閱的表達式:
__key空間/事件@數據庫id__:對象
比如:
__keyspace@0__:mykey 訂閱數據庫0中 mykey的相關事件
__keyevent@0__:del 訂閱數據庫0中的 del事件
兩者的區別在於,一個是符合key就通知,一個是符合事件就通知。
對於key在哪個數據庫,我們很難知道,那么可以使用"*"匹配所有:
__key*__:*
PHP實現
在PHP里可以使用PHPRedis擴展,注意事項取消連接超時
$redis = new Redis();
$redis->connect("127.0.0.1");
$redis->setOption(\Redis::OPT_READ_TIMEOUT,-1);
$redis->psubscribe(['__key*__:*'], 'psCallback');
function psCallback($redis, $pattern, $chan, $msg)
{
echo "Pattern: $pattern\n"; //訂閱的模式
echo "Channel: $chan\n"; //符合模式的頻道
echo "Payload: $msg\n\n"; //訂閱的key
}
后台運行
Linux下,可以使用nohup php file.php 在后台持續運行