日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring boot 集成redis监听Key值事件失效

發布時間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot 集成redis监听Key值事件失效 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有時需要監聽Redis的事件從而在Redis事件發生時添加一些后續操作;在實際開發過程中,有這么一個需求,監聽Redis中的鍵狀態,從而去更改程序中數據的狀態;實現方法如下:

  • 方法一: 實現redis提供的MessageListener接口

    首先開啟Redis的監聽事件,大約在Redis配置文件的889行,或者直接搜索notify-keyspace-events,將其更改為你需要監聽的類型

    這段注釋已經寫得非常清楚了,建議想了解配置詳情的哥們可以把下面這部分注釋復制粘貼到翻譯軟件中自己理解,如果急于功能實現的話,那么就把notify-keyspace-events屬性設置為EA

    # Redis can notify Pub/Sub clients about events happening in the key space. # This feature is documented at http://redis.io/topics/notifications # # For instance if keyspace events notification is enabled, and a client # performs a DEL operation on key "foo" stored in the Database 0, two # messages will be published via Pub/Sub: # # PUBLISH __keyspace@0__:foo del # PUBLISH __keyevent@0__:del foo # # It is possible to select the events that Redis will notify among a set # of classes. Every class is identified by a single character: # # K Keyspace events, published with __keyspace@<db>__ prefix. # E Keyevent events, published with __keyevent@<db>__ prefix. # g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... # $ String commands # l List commands # s Set commands # h Hash commands # z Sorted set commands # x Expired events (events generated every time a key expires) # e Evicted events (events generated when a key is evicted for maxmemory) # A Alias for g$lshzxe, so that the "AKE" string means all the events. # # The "notify-keyspace-events" takes as argument a string that is composed # of zero or multiple characters. The empty string means that notifications # are disabled. # # Example: to enable list and generic events, from the point of view of the # event name, use: # # notify-keyspace-events Elg # # Example 2: to get the stream of the expired keys subscribing to channel # name __keyevent@0__:expired use: # notify-keyspace-events EA # # By default all notifications are disabled because most users don't need # this feature and the feature has some overhead. Note that if you don't # specify at least one of K or E, no events will be delivered. # notify-keyspace-events ""

    其次需要實現MessageListener接口

    @Component @Slf4j public class MyMessageListener implements MessageListener{@Overridepublic void onMessage(Message message, byte[] bytes) {log.debug("鍵值{}",message.toString());} }

    然后需要在配置類中將這個事件監聽添加到Redis容器中

    @Configuration public class Configurer{@BeanMyMessageListener myMessageListener(){new MyMessageListener();}@BeanRedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,MyMessageListener myMessageListener) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.addMessageListener(myMessageListener,new PatternTopic("__keyevent@*__:expired"))return container;}}
  • 方法二: 繼承redis提供的KeyExpirationEventMessageListener類

    @Component @Slf4j public class MyRedisKeyExpirationListener extends KeyExpirationEventMessageListener {public MyRedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {super(listenerContainer);}@Overridepublic void onMessage(Message message, byte[] pattern) {log.debug("鍵值{}",message.toString());} }

    這種方法省去了將監聽器添加到容器中的步驟,因為在KeyExpirationEventMessageListener類中它已經將監聽添加到容器中

    private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@*__:expired");protected void doRegister(RedisMessageListenerContainer listenerContainer) {listenerContainer.addMessageListener(this, KEYEVENT_EXPIRED_TOPIC); }

    集成KeyExpirationEventMessageListener類無疑是一種簡單的模式,但是它只能監聽key失效的情況,于是我參考方法一和方法二,將Topic配置交給相應的監聽器實現如下:

  • 方法三

    public abstract class AbstractMessageListener implements MessageListener, InitializingBean {private final RedisMessageListenerContainer listenerContainer;protected AbstractMessageListener(RedisMessageListenerContainer listenerContainer) {this.listenerContainer = listenerContainer;}public void afterPropertiesSet() throws Exception {listenerContainer.addMessageListener(this, getTopic());}protected abstract Topic getTopic(); }

    通過實現上面的抽象接口從而實現監聽格式和事件的注冊關系

    @Slf4j public class KeyExpirationMessageListener extends AbstractMessageListener {public KeyExpirationMessageListener(RedisMessageListenerContainer listenerContainer, List<KeyHandle> keyHandleList) {super(listenerContainer);}@Overrideprotected Topic getTopic() {return new PatternTopic("__keyevent@*__:expired");}@Overridepublic void onMessage(Message message, byte[] bytes) {log.debug("鍵值{}",message.toString());} }

那么問題來了:在項目開始運行時,方法三可以順利的運行并沒有任何問題;但是在將Redis服務重啟后事件監聽竟然毫無反應。當我把方法二的代碼啟用后,程序又可以順利的運行。當時因為著急處理其它問題,所以當程序順利運行后就沒有再管這個問題;又過了一段安然的日子,Redis重啟后,又出現了這個尷尬的問題,這時我決定將它徹徹底底的消滅掉,于是我在想,難道Redis只認自己的親兒子?當然這么可笑的想法只是一閃而過,親兒子特殊肯定有特殊的地方,于是我開始考慮是不是KeyExpirationEventMessageListener類中做了什么特殊的處理;說干就干,我打開了它的源碼,沒有任何特殊的地方,又打開了它的爸爸KeyspaceEventMessageListener類,果然一份驚喜在等著我

private String keyspaceNotificationsConfigParameter = "EA";public void init() {if (StringUtils.hasText(this.keyspaceNotificationsConfigParameter)) {RedisConnection connection = this.listenerContainer.getConnectionFactory().getConnection();try {Properties config = connection.getConfig("notify-keyspace-events");if (!StringUtils.hasText(config.getProperty("notify-keyspace-events"))) {connection.setConfig("notify-keyspace-events", this.keyspaceNotificationsConfigParameter);}} finally {connection.close();}}this.doRegister(this.listenerContainer); }

notify-keyspace-events這個屬性我們不太陌生,這個值有個特性就是當它的設置值為空值時則默認是不啟用事件的,但是這個類在它為空的時候設置了默認值。這可能就是我們方法三中的類不受支持的原因。于是我打開Redis配置文件,此時它是這樣的,為了能更清楚的展示出我傻逼的一面,我用截圖來說明一下問題:

現在問題已經找到了,我在將notify-keyspace-events設置成我想要的值之后,沒有將默認配置注釋掉!沒有將默認配置注釋掉!沒有將默認配置注釋掉!于是我決定把這次傻逼行為記錄下來,不斷的提醒自己

細節不僅能打敗愛情,也能打敗程序員!!!!!

順便再說一句,在翻看源碼的時候,我發現,還有一種方法可以實現事件監聽,那就是直接實現KeyExpirationEventMessageListener的爸爸KeyspaceEventMessageListener類,但是它的名字已經標記了它是監聽 __keyspace事件,不知道為什么程序里監聽的是 __keyevent事件,我想這可能就是大佬吧,讓你琢磨不透

原文章地址請點擊此處鏈接

總結

以上是生活随笔為你收集整理的spring boot 集成redis监听Key值事件失效的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。