Redis键通知(事件通知)

Redis键通知(事件通知)

通常,对于Redis这款中间件,最多的应该是作为缓存来使用,比较好的做法是会给Redis中的key设置一个过期时间,过期之后自动删除。那么,我们可能会有这样的需求,如果一个key被删除了,或者过期了,能否通知使用redis的应用程序呢,其实是有方法的。

从Redis:2.8.0开始,提供了键空间通知的功能,详见官方文档Redis Keyspace Notifications - Redis 。原理就是基于Redis的PUB/SUB机制,当键被发生了某种操作时,Redis会往特定的channel发布特定格式的消息,Redis客户端订阅相关channel就可以接受到消息并作相应的处理。

channel格式:keyevent@数据库ID:操作类型

# 删除键
__keyevent@0__:del
# 键过期
__keyevent@0__:expired
...

默认情况下,Redis键通知功能是禁用的,开启需要在配置文件中增加名字为notify-keyspace-events的配置,具体值配置为多少,官方文档中其实也给出了

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
t     Stream commands
d     Module key type events
x     Expired events (events generated every time a key expires)
e     Evicted events (events generated when a key is evicted for maxmemory)
m     Key miss events (events generated when a key that doesn't exist is accessed)
A     Alias for "g$lshztxed", so that the "AKE" string means all the events except "m".

我们需要接收键事件,E必须配置,否则其他配置不生效,具体怎么组合,看具体使用场景,举些例子

Eg 对某个键调用DEL,EXPIRE操作时,会收到通知
Ex 当某个键过期后会收到通知
Em 当检索某个不存在的键时会收到通知

开始具体实操一下,需求监听键过期事件

  1. 修改redis.conf配置文件并重启Redis

在这里插入图片描述

  1. 新建Maven项目,导入Redis相关依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 配置监听器容器
@Configuration
public class RedisConfig {

    @Bean
    public RedisMessageListenerContainer listenerContainer(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(new KeyExpirationMessageListener(), new PatternTopic("__keyevent@0__:expired"));
        return container;
    }
}

@Slf4j
public class KeyExpirationMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message, byte[] pattern) {
        log.info("监听到键过期消息,消息内容:{},消息对应的键为:{}", message, new String(pattern));
        // TODO 业务逻辑
    }
}
  1. 启动项目,使用Redis客户端设置一个键,超时时间设置为10秒钟,观察控制台打印信息
    在这里插入图片描述
    在这里插入图片描述
  2. 当然,这是一种通用的配置方式,但如果仅仅是为了接收键过期提醒,可以使用spring-boot-starter-data-redis依赖中提供的KeyExpirationEventMessageListener监听器,本身已经实现了MessageListener接口,同时,又实现了ApplicationEventPublisherAware接口,具备了使用Spring事件驱动的功能

在这里插入图片描述
使用时需要配置RedisMessageListenerContainer、KeyExpirationEventMessageListener、ApplicationListener

@Slf4j
@Configuration
public class RedisConfig {

    @Bean
    public RedisMessageListenerContainer listenerContainer(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //container.addMessageListener(new KeyExpirationMessageListener(), new PatternTopic("__keyevent@0__:expired"));
        return container;
    }


    @Bean
    public KeyExpirationEventMessageListener keyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer) {
        return new KeyExpirationEventMessageListener(listenerContainer);
    }

    @Bean
    public ApplicationListener applicationListener() {
        return (ApplicationListener<RedisKeyExpiredEvent>) event -> {
            log.info("监听到键过期消息,消息对应的键为:{},消息所属的channel为:{}", new String(event.getSource()), event.getChannel());
        };
    }
}

同样的,会在控制台看到相关信息
在这里插入图片描述
最后,需要说明的一点,Redis的键通知功能并不是一种完全可靠的机制,某些情况下通知不可达,比如因为网络问题导致应用跟Redis server断线重连,那么在断线时间范围内,有键触发了通知也无法送达应用,且事后无补偿,所以在可靠性要求很高的场景下并不适用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值