1. 程式人生 > 其它 >redis key失效後觸發事件

redis key失效後觸發事件

實現思路

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 表示過期事件