RedisKey的失效监听器KeyExpirationEventMessageListener

利用KeyExpirationEventMessageListener实现redis的key失效监听。

在使用redis时,所有的key都要设置过期时间,过期之后,redis就会把对应的key清除掉。此方法可以监听redis的key失效,在失效时做一些逻辑处理。话不多说,上代码。
依赖:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

实现:

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) {

        // 只监听指定redis数据库的key过期事件
        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"
        // 触发key失效发布的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();
        }
    }

}

监听处理类

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存储所有实现Strategy接口的Bean
     * key:beanName
     * value:实现Strategy接口Bean
     */
    private final Map<String, PushMessageStrategy> strategyMap = Maps.newConcurrentMap();

    /**
     * 注入所有实现了Strategy接口的Bean
     *
     * @param strategyMap the strategy map
     */
    @Autowired
    public PushMessageStrategyContext(Map<String, PushMessageStrategy> strategyMap) {
        strategyMap.forEach(this.strategyMap::put);
    }

    /**
     * 策略监听redis所有过期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("找不到对应的策略:{}", strategyMap.get(beanName));
        }
    }

}

public interface PushMessageStrategy {
  void handleRedisExpireKey(String redisInvalidKey);
}

大家在使用的时候,可以针对自己不同的场景,实现PushMessageStrategy 接口,重写handleRedisExpireKey方法。在方法中处理不同的逻辑。

首先,在redis’中有key失效过期时,AgentOrderRedisKeyExpiredListener 监听到redis实现,会执行doHandleMessage方法,方法中会调用PushMessageStrategyContext 的获取不同策略的Bean,进行业务操作。至此,监听redis中key失效完成。欢迎大家点赞收藏使用。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Java 中,你可以使用 Redisson 这个 Redis 客户端库来实现 Redis 键的失效监听。Redisson 提供了 `RKeys` 类来操作 Redis 的键,并且可以通过 `addListener` 方法添加键的监听器。以下是一个示例代码: ```java import org.redisson.Redisson; import org.redisson.api.RKeys; import org.redisson.api.RedissonClient; import org.redisson.api.listener.KeyspaceExpiredListener; public class RedisKeyExpirationListenerExample { public static void main(String[] args) { // 创建 Redisson 客户端 RedissonClient redisson = Redisson.create(); // 获取键操作对象 RKeys keys = redisson.getKeys(); // 添加键失效监听器 keys.addListener(new KeyspaceExpiredListener() { @Override public void onExpired(String key) { System.out.println("Key expired: " + key); // 在这里处理键失效事件 } }); // 等待键失效事件发生 try { Thread.sleep(60000); // 60秒 } catch (InterruptedException e) { e.printStackTrace(); } // 关闭 Redisson 客户端 redisson.shutdown(); } } ``` 在上述示例中,我们使用 Redisson 创建了一个 Redis 客户端,并通过 `getKeys()` 方法获取了键操作对象 `RKeys`。然后,我们使用 `addListener` 方法添加了一个键失效监听器 `KeyspaceExpiredListener`,并在回调方法中处理键失效事件。 你可以根据需要在回调方法中编写自己的处理逻辑。在示例中,我们简单地打印出了失效的键。 最后,我们通过 `Thread.sleep` 方法让程序等待一段时间,以便触发键失效事件。在实际应用中,你可以根据自己的需求来决定如何触发键失效事件。 请确保你已经在项目中引入了 Redisson 的依赖。你可以通过 Maven 或 Gradle 在项目的构建文件中添加以下依赖: Maven: ```xml <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.16.1</version> </dependency> ``` Gradle: ```groovy implementation 'org.redisson:redisson:3.16.1' ``` 请注意,上述示例中假设 Redis 运行在本地主机。你需要根据你自己的实际情况进行适配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小故事呀

您的打赏是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值