springboot Redis 事件监听

叙述

Keyspace 通知使得客户端可以通过订阅频道或模式,来接收那些以某种方式改动了 Redis 数据集的事件(触发某些事件后可以向指定的频道发送通知),该功能需要 Redis 版本大于 2.8。

事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发,因此所有支持订阅与发布功能的客户端都可以在无须做任何修改的情况下,直接使用此功能。

因为 Redis 目前的订阅与发布功能采取的是发送即忘(fire and forget)策略,所以如果你的程序需要可靠事件通知(reliable notification of events),那么目前的键空间通知可能并不适合你:当订阅事件的客户端断线时,它会丢失所有在断线期间分发给它的事件。


事件类型

对于每个修改数据库的操作,键空间通知都会发送两种不同类型的事件:键空间通知(key-space)和键事件通知(key-event)。

当 del mykey 命令执行时:

  • 键空间频道的订阅者将接收到被执行的事件的名字,在这个例子中,就是 del
  • 键事件频道的订阅者将接收到被执行事件的键的名字,在这个例子中,就是 mykey

因为开启键空间通知功能需要消耗一些 CPU,所以在默认配置下,该功能处于关闭状态。

修改 redis.conf 中的  notify-keyspace-events  参数,参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知:

 

输入的参数中至少要有一个 K 或者 E,否则的话,不管其余的参数是什么,都不会有任何通知被分发。

如: notify-keyspace-events "Ex"  表示对过期事件进行通知发送; notify-keyspace-events "kx" 表示想监控某个 key 的失效事件。将参数设为字符串 AKE 表示发送所有类型的通知。

演示

客户端订阅  subscribe __keyevent@0__:expired 

在另一个客户端执行  setex name 10 txl ,10 秒过后,订阅端就会接收到消息:


教程

Redis配置

修改配置文件redis.conf(Windows为redis.windows.conf)

  • 打开该配置文件(位置取决于自己的安装位置),找到Event notification部分。
  • 将notify-keyspace-events Ex的注释打开或者添加该配置,其中E代表Keyevent,此种通知会返回key的名字,x代表超时事件。
  • 如果notify-keyspace-events ""配置没有被注释的话要注释掉,否则不会生效。
  • 保存后重启redis,一定要使用当前配置文件重启,例如src/redis-server redis.conf

springboot配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  redis:
    # 连接超时 毫秒
    connectTimeout: 1800
    # 运行超时 毫秒
    timeout: 7200
    host: 127.0.0.1
    port: 6379
    database: 1
    password:
    jedis:
      pool:
        # 最大空闲(cpu*2)
        maxIdle: 16
        # 最小空闲
        minIdle: 0
        # 最大阻塞等待时间(负数表示没限制)毫秒
        maxWait: 3600
        # 最大连接数(大于cpu*2)
        maxActive: 24
    # 键事件过期监听 1 代表使用了哪个DB 参考 database
    listen:
      keyEvent: __keyevent@1__:expired
@Data
@Component
@ConfigurationProperties(
        prefix = "spring.redis.listen"
)
public class RedisProperties {
    private String keyEvent;
}
@Configuration
public class RedisConfig {
    @Autowired
    private RedisConnectionFactory factory;
    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }

    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }

    /**
     * redis消息监听器容器
     * 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
     * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic(redisProperties.getKeyEvent()));
        return container;
    }

    /**
     * keyEvent 专用
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(KeyEventReceiver receiver) {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

}
@Component
public class KeyEventReceiver {

    //监听键事件,过期事件
    public void receiveMessage(String message) throws Exception {

        log.error("过期键 <" + message + ">");

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值