redis 超時失效key 的監聽觸發

2021-09-02 00:14:02 字數 4688 閱讀 1438

redis自2.8.0之後版本提供keyspace notifications功能,允許客戶訂閱pub / sub頻道,以便以某種方式接收影響redis資料集的事件。

可能收到的事件的例子如下: 

所有影響給定鍵的命令。

所有接收lpush操作的金鑰。

所有金鑰在資料庫中過期0。

因為 redis 目前的訂閱與發布功能採取的是傳送即忘(fire and forget)策略, 所以如果你的程式需要可靠事件通知(reliable notification of events), 那麼目前的鍵空間通知可能並不適合你:當訂閱事件的客戶端斷線時, 它會丟失所有在斷線期間分發給它的事件。並不能確保訊息送達。未來有計畫允許更可靠的事件傳遞,但可能這將在更一般的層面上解決,或者為pub / sub本身帶來可靠性,或者允許lua指令碼攔截pub / sub訊息來執行諸如推送將事件列入清單。

對於每個修改資料庫的操作,鍵空間通知都會傳送兩種不同型別的事件訊息:keyspace 和 keyevent。以 keyspace 為字首的頻道被稱為鍵空間通知(key-space notification), 而以 keyevent 為字首的頻道則被稱為鍵事件通知(key-event notification)。

事件是用  __keyspace@db__:keypattern 或者  __keyevent@db__:opstype 的格式來發布訊息的。

db表示在第幾個庫;keypattern則是表示需要監控的鍵模式(可以用萬用字元,如:__key*__:*);opstype則表示操作型別。因此,如果想要訂閱特殊的key上的事件,應該是訂閱keyspace。

比如說,對 0 號資料庫的鍵 mykey 執行 del 命令時, 系統將分發兩條訊息, 相當於執行以下兩個 publish 命令:

publish __keyspace@0__:samplekey del

publish __keyevent@0__:del samplekey

訂閱第乙個頻道 __keyspace@0__:mykey 可以接收 0 號資料庫中所有修改鍵 mykey 的事件, 而訂閱第二個頻道 __keyevent@0__:del 則可以接收 0 號資料庫中所有執行 del 命令的鍵。

字元

傳送通知

k鍵空間通知,所有通知以keyspace@為字首,針對key

e鍵事件通知,所有通知以keyevent@為字首,針對event

gdel 、 expire 、 rename 等型別無關的通用命令的通知

$字串命令的通知

l列表命令的通知

s集合命令的通知

h雜湊命令的通知

z有序集合命令的通知

x過期事件:每當有過期鍵被刪除時傳送

e驅逐(evict)事件:每當有鍵因為 maxmemory 政策而被刪除時傳送

a引數 g$lshzxe 的別名,相當於是all

輸入的引數中至少要有乙個 k 或者 e , 否則的話, 不管其餘的引數是什麼, 都不會有任何通知被分發。上表中斜體的部分為通用的操作或者事件,而黑體則表示特定資料型別的操作。配置檔案中修改 notify-keyspace-events 「kx」,注意:這個雙引號是一定要的,否則配置不成功,啟動也不報錯。例如,「kx」表示想監控某個key的失效事件。

也可以通過config配置:config set notify-keyspace-events ex (但非持久化)

redis 使用以下兩種方式刪除過期的鍵:

1.當乙個鍵被訪問時,程式會對這個鍵進行檢查,如果鍵已經過期,那麼該鍵將被刪除。

2.底層系統會在後台查詢並刪除那些過期的鍵,從而處理那些已經過期、但是不會被訪問到的鍵。

當過期鍵被以上兩個程式的任意乙個發現、 並且將鍵從資料庫中刪除時, redis 會產生乙個 expired 通知。

因此, redis 產生 expired 通知的時間為過期鍵被刪除的時候, 而不是鍵的生存時間變為 0 的時候。

由於通知收到的是redis key,value已經過期,無法收到,所以需要在key上標記業務資料。

實現思路:

1,利用messagelisteneradapter,spring本身已經提供了的實現方式。

首先自定義乙個messagedelegate 介面並實現

1 public inte***ce mymessagedelegate 

8 9 public class myrediskeyexpiredmessagedelegate implements messagedelegate

xml相關配置

具體可參考官方文件:

2.即自定義乙個keyexpiredlistener類繼承自jedispubsub。

import redis.clients.jedis.jedispubsub;

public class keyexpiredlistener extends jedispubsub

@override

public void onpmessage(string pattern, string channel, string message)

}

訂閱者

public class subscriber 

}

測試

public class testjedis 

}

結果

onpsubscribe __key*__:* 1

onpmessage pattern __key*__:* __keyevent@0__:expired sla_zw_line_lock_sssssss

onpmessage pattern __key*__:* __keyevent@0__:expired sla_zw_line_lock_sssssss

其中第一行的列印是啟動訂閱者的時候才列印1次

3,發布和訂閱的方式

特性介紹

pub/sub功能(means publish, subscribe)即發布及訂閱功能。基於事件的系統中,pub/sub是目前廣泛使用的通訊模型,它採用事件作為基本的通訊機制,提供大規模系統所要求的鬆散耦合的互動模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的乙個事件或一類事件;發布者(如伺服器)可將訂閱者感興趣的事件隨時通知相關訂閱者。

監聽者

public class subscriberlistener extends jedispubsub 

@override

public void onmessage(string channel, string message)

@override

public void onsubscribe(string channel, int subscribedchannels)

@override

public void onunsubscribe(string channel, int subscribedchannels)

}

發布者

public class publisher extends thread

@override

public void run() else

} catch (ioexception e)

}}

訂閱者

public class pubsubdemo 

}

測試類

public class subthread extends thread 

@override

public void run() catch (exception e) finally }}

}

測試結果

redis pool is starting, redis ip 127.0.0.1, redis port 6379

subscribe redis, channel mychannel, thread will be blocked

subscribe redis channel success, channel mychannel, subscribedchannels 1

mytest -------------我鍵入的值

receive redis published message, channel mychannel, message mytest

this is my second test -------------我鍵入的值

receive redis published message, channel mychannel, message this is my second test

redis 超時失效key 的監聽觸發

1.事件通過 redis 的訂閱與發布功能 pub sub 來進行分發,故需要訂 閱 keyevent 0 expired 通道 0表示db0 根據自己的dbindex選擇合適的數字 2.修改 redis.conf 檔案 修改 notify keyspace events ex k 鍵空間通知,以 ...

redis 超時失效key 的監聽觸發

1.事件通過 redis 的訂閱與發布功能 pub sub 來進行分發,故需要訂 閱 keyevent 0 expired 通道 0表示db0 根據自己的dbindex選擇合適的數字 2.修改 redis.conf 檔案 修改 notify keyspace events ex k 鍵空間通知,以 ...

Redis監聽Key失效

之前我使用過使用redisson這種redis的框架實現過延時傳送。今天突然好奇,在springboot中,redis能監聽到key失效事件嗎?經過查資料,答案是肯定的,可以監聽key失效,但是有缺陷,監聽事件裡面只能拿到key,不能拿到這個key對應的value。所以說,在生成這個key的時候,需...