redis键(key)失效后触发事件

  • 1、试用场景
  • 2、本文应用场景
  • 3、实现思路
  • 4、实现流程
  • 此方法有几个注意事项:
  • 关于简易的redis分布式锁会在下一章写到


1、试用场景

1、每条消息的失效时间不一样
2、每条消息存储时长不一样

2、本文应用场景

项目需求:
用户1 提交需求至 用户处理中心,处理中心收到后有处理选项,点击处理选项,说明处理中心收到并且已 经开始处理,如果未处理,10分钟后再次推送一条消息,通知其处理,流程结束。
本来最好的处理方式是用rabbitMq延迟队列,大致思路和逻辑为设置一个延迟队列,发送消息时对消息设置延迟时长,但是由于项目是个小型的小程序项目,功能不多,没有用到mq,为了减少一个中间件的维护,所以还是研究redis的解决方案

3、实现思路

1、每条消息的发送时间不同,所以每条消息失效时间自然也不一样,放入延迟队列不适用、
2、定时循环队列,觉得比较占用资源。
3、想到了redis的键值失效功能,消息存入redis时设置10分钟失效,如果中间有处理此消息,那么去内存中删掉此消息,这样就能保证redis中存储的消息都是需要发送并且有效的,到失效触发消息时不用做任何判断直接发送即可

4、实现流程

1、首先做一个redis的配置类

@Configuration
public class RedisListenerConfig {
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

2、配置类做完后,便可以设置监听器了,写一个全新的监听器,继承KeyExpirationEventMessageListener类,其中onMessage方法便是键失效后触发的事件,重写该事件即可

@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    /**
     * redis 分布式锁工具类
     */
    @Autowired
    private DistributedLock distributedLock;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 针对redis数据失效事件,进行数据处理
     * @param message
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        
		System.out.println("取到失效的键是:" + message.toString());
    }
}

此方法有几个注意事项:

1、监听消息事件触发是发送给所有监听者的,所以在多监听者的时候需要做一个redis分布式锁,保证失效消息不要重复被消费。
2、此监听是redis中所有的消息失效都会触发,所以要进行key值的过滤,来过滤出我们需要处理的消息

关于简易的redis分布式锁会在下一章写到