RedisKey的失效監(jiān)聽(tīng)器KeyExpirationEventMessageListener問(wèn)題
RedisKey的失效監(jiān)聽(tīng)器KeyExpirationEventMessageListener
利用KeyExpirationEventMessageListener實(shí)現(xiàn)redis的key失效監(jiān)聽(tīng)。
在使用redis時(shí),所有的key都要設(shè)置過(guò)期時(shí)間,過(guò)期之后,redis就會(huì)把對(duì)應(yīng)的key清除掉。
此方法可以監(jiān)聽(tīng)redis的key失效,在失效時(shí)做一些邏輯處理。話不多說(shuō),上代碼。
依賴(lài)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>實(shí)現(xiàn)
import com.upbim.twin.park.common.constans.Constants;
import com.upbim.twin.park.server.strategy.PushMessageStrategyContext;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.stereotype.Service;
import java.util.UUID;
import static com.upbim.twin.park.common.constans.Constants.TRACE_ID;
@Slf4j
@Service
public class AgentOrderRedisKeyExpiredListener extends KeyExpirationEventMessageListener {
@Autowired
private PushMessageStrategyContext pushMessageStrategyContext;
@Autowired
private RedisProperties redisProperties;
/**
* Creates new MessageListener for {@code __keyevent@*__:expired} messages.
*
* @param listenerContainer must not be {@literal null}.
*/
public AgentOrderRedisKeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
protected void doRegister(RedisMessageListenerContainer listenerContainer) {
// 只監(jiān)聽(tīng)指定redis數(shù)據(jù)庫(kù)的key過(guò)期事件
Topic topic = new PatternTopic(String.format("__keyevent@%s__:expired", redisProperties.getDatabase()));
listenerContainer.addMessageListener(this, topic);
}
@Override
protected void doHandleMessage(Message message) {
// 訂閱的topic: new String(message.getChannel(), UTF_8) ---> "__keyevent@0__:expired"
// 觸發(fā)key失效發(fā)布的key:new String(message.getBody(), UTF_8) ---> "demoKey"
MDC.put(TRACE_ID, UUID.randomUUID().toString());
try {
log.info(String.format("Redis key expired event:%s", message.toString()));
String beanName = message.toString().split(Constants.COLON)[Constants.ONE];
pushMessageStrategyContext.handleRedisExpireKey(beanName, message.toString());
super.doHandleMessage(message);
} finally {
MDC.clear();
}
}
}監(jiān)聽(tīng)處理類(lèi)
package com.upbim.twin.park.server.strategy;
import com.google.common.collect.Maps;
import com.upbim.twin.park.server.strategy.nozzle.PushMessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class PushMessageStrategyContext {
/**
* 使用線程安全的ConcurrentHashMap存儲(chǔ)所有實(shí)現(xiàn)Strategy接口的Bean
* key:beanName
* value:實(shí)現(xiàn)Strategy接口Bean
*/
private final Map<String, PushMessageStrategy> strategyMap = Maps.newConcurrentMap();
/**
* 注入所有實(shí)現(xiàn)了Strategy接口的Bean
*
* @param strategyMap the strategy map
*/
@Autowired
public PushMessageStrategyContext(Map<String, PushMessageStrategy> strategyMap) {
strategyMap.forEach(this.strategyMap::put);
}
/**
* 策略監(jiān)聽(tīng)redis所有過(guò)期key
*
* @param beanName the bean name
* @param redisInvalidKey the redis invalid key
* @return
*/
public void handleRedisExpireKey(String beanName, String redisInvalidKey) {
if (Objects.nonNull(strategyMap.get(beanName))) {
strategyMap.get(beanName).handleRedisExpireKey(redisInvalidKey);
} else {
log.warn("找不到對(duì)應(yīng)的策略:{}", strategyMap.get(beanName));
}
}
}public interface PushMessageStrategy {
void handleRedisExpireKey(String redisInvalidKey);
}大家在使用的時(shí)候,可以針對(duì)自己不同的場(chǎng)景,實(shí)現(xiàn)PushMessageStrategy 接口,重寫(xiě)handleRedisExpireKey方法。
在方法中處理不同的邏輯。
首先,在redis’中有key失效過(guò)期時(shí),AgentOrderRedisKeyExpiredListener 監(jiān)聽(tīng)到redis實(shí)現(xiàn),會(huì)執(zhí)行doHandleMessage方法,方法中會(huì)調(diào)用PushMessageStrategyContext 的獲取不同策略的Bean,進(jìn)行業(yè)務(wù)操作。
至此,監(jiān)聽(tīng)redis中key失效完成。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot RestTemplate 簡(jiǎn)單包裝解析
這篇文章主要介紹了SpringBoot RestTemplate 簡(jiǎn)單包裝解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
關(guān)于Spring?Boot項(xiàng)目的?log4j2?核彈漏洞問(wèn)題(一行代碼配置搞定)
相信昨天,很多小伙伴都因?yàn)長(zhǎng)og4j2的史詩(shī)級(jí)漏洞忙翻了吧,不過(guò)我看到群里發(fā)出來(lái)的各種修復(fù)方法,還真是不好看...所以這里也提一下Spring Boot用戶(hù)怎么修復(fù)最簡(jiǎn)單吧,對(duì)Spring Boot log4j2 核彈漏洞問(wèn)題感興趣的朋友參考下吧2021-12-12
SpringBoot + Maven 多環(huán)境打包實(shí)現(xiàn)方法
本文介紹如何在SpringBoot項(xiàng)目中實(shí)現(xiàn)不同環(huán)境的配置切換及Maven多環(huán)境打包的方法,包括配置文件的選擇與加載機(jī)制,以及如何通過(guò)POM文件進(jìn)行多環(huán)境打包,感興趣的朋友跟隨小編一起看看吧2025-12-12
用Rational Rose逆向工程(java)生成類(lèi)圖(教程和錯(cuò)誤解決)
Rational Rose有個(gè)很方便的功能,將項(xiàng)目中的JAVA代碼自動(dòng)轉(zhuǎn)換成UML類(lèi)圖2013-02-02
一些java二進(jìn)制的相關(guān)基礎(chǔ)知識(shí)
這篇文章主要介紹了一些java二進(jìn)制的相關(guān)基礎(chǔ)知識(shí),在Java語(yǔ)言中byte代表最小計(jì)量單位,byte由8位2進(jìn)制數(shù)組成。,需要的朋友可以參考下2019-06-06
一文詳解SpringBoot如何優(yōu)雅地實(shí)現(xiàn)異步調(diào)用
SpringBoot想必大家都用過(guò),但是大家平時(shí)使用發(fā)布的接口大都是同步的,那么你知道如何優(yōu)雅的實(shí)現(xiàn)異步呢?這篇文章就來(lái)和大家詳細(xì)聊聊2023-03-03
Java 基于AQS實(shí)現(xiàn)自定義同步器的示例
這篇文章主要介紹了Java 基于AQS實(shí)現(xiàn)自定義同步器的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-03-03
用java的spring實(shí)現(xiàn)一個(gè)簡(jiǎn)單的IOC容器示例代碼
本篇文章主要介紹了用java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的IOC容器示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03

