SpringBoot实现Redis失效监听事件—KeyExpirationEventMessageListener

使用场景:当redis某个key过期的时候,我们希望处理一些业务例如发消息或者取消订单等,当然也可以使用中间件mq来实现,之前的文章里有写rocketMq实现消息的通知和消费,这篇文章主要是用redis来实现

1.引入依赖

        
            org.springframework.boot
            spring-boot-starter-data-redis
        

yml配置

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456

2.配置文件

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * key过期事件订阅需要
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        return container;
    }

}

3.自定义监听器,需要继承KeyExpirationEventMessageListener

@Component
public class RedisListener extends KeyExpirationEventMessageListener {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final String SET_NX = "setnx:";

    public RedisListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);

    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 获取过期的key,可以做自己的业务
        String expiredKey = message.toString();
        // 利用redis setIfAbsent命令,如果为空set返回true,如果不为空返回false,类似setnx加锁操作
        Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(SET_NX + expiredKey, String.valueOf(System.currentTimeMillis()),10, TimeUnit.SECONDS);
        if (aBoolean){
            // 避免多个服务监听情况下重复消费
            // 注意:只能获取失效的key值,不能获取key对应的value值
            System.out.println(expiredKey);
        }
    }
}

我们需要重写onMessage方法,当有key过期的时候这个方法可以获取获取的key,并处理自己的业务
如果我们是多台机器部署,那么我们还需要加锁操作,避免消息的重复消费,这里利用了stringRedisTemplate.opsForValue().setIfAbsent命令可以帮我们完成setnx加锁的操作,如果为空set返回true,如果不为空返回false,因为redis是单线程所以可以保证只消费一次,setIfAbsent同时要加上过期时间,注意redis版本过低的话可能没有这个方法

你可能感兴趣的:(SpringBoot实现Redis失效监听事件—KeyExpirationEventMessageListener)