redis key失效後觸發事件
阿新 • • 發佈:2021-01-07
實現思路
1、每條訊息的傳送時間不同,所以每條訊息失效時間自然也不一樣,放入延遲佇列不適用、
2、定時迴圈佇列,覺得比較佔用資源。
3、想到了redis的鍵值失效功能,訊息存入redis時設定10分鐘失效,如果中間有處理此訊息,那麼去記憶體中刪掉此訊息,這樣就能保證redis中儲存的訊息都是需要傳送並且有效的,到失效觸發訊息時不用做任何判斷直接傳送即可
實現流程
redis的超時監聽,只需修改配置檔案redis.conf中的:notify-keyspace-events Ex
K 鍵空間通知,以[email protected]<db>__為字首
E 鍵事件通知,以 [email protected]<db>__為字首
g del , expipre , rename 等型別無關的通用命令的通知, ...
$ String命令
l List命令
s Set命令
h Hash命令
z 有序集合命令
x 過期事件(每次key過期時生成)
e 驅逐事件(當key在記憶體滿了被清除時生成)
A g$lshzxe的別名,因此”AKE”意味著所有的事件
1、首先做一個redis的配置類
@Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
2、配置類做完後,便可以設定監聽器了,寫一個全新的監聽器,繼承KeyExpirationEventMessageListener類,其中onMessage方法便是鍵失效後觸發的事件,重寫該事件即可
@Slf4j @Component public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } /** * 針對redis資料失效事件,進行資料處理 * @param message * @param pattern */ @Override public void onMessage(Message message, byte[] pattern) { String expKey = message.toString(); String date = new DateTime().toString("yyyy-MM-dd HH:mm:ss"); log.info("{}---該key(訂單號):{} 失效了~", date, expKey); log.info("業務程式碼執行結束..."); } }
此方法有幾個注意事項:
1、監聽訊息事件觸發是傳送給所有監聽者的,所以在多監聽者的時候需要做一個redis分散式鎖,保證失效訊息不要重複被消費。
2、此監聽是redis中所有的訊息失效都會觸發,所以要進行key值的過濾,來過濾出我們需要處理的訊息
時間關係,以下尚未測試
註冊redis key過期Listener
@PostConstruct
private void init() {
// 因為此方法阻塞執行緒
new Thread(new Runnable() {
@Override
public void run() {
// 訂閱redis key過期時間,需要reids 伺服器配置notify-keyspace-events Ex
jedisPool.getResource().subscribe(redisKeyExpiredListener, "[email protected]__:expired");
}
}).start();
}
[email protected]:expired
__keyevent必須以此開頭;
@2 表示監聽第二個資料庫;
:expired 表示過期事件