Redis监听事件

文章介绍了如何在SpringBoot应用中配置Redis模板,设置序列化方式,并创建Redis监听容器来监听Redis的键过期事件。当订单任务过期时,通过监听器变更任务状态。同时,该配置也可应用于其他类型的业务过期事件处理。
摘要由CSDN通过智能技术生成

Redis监听过期事件处理

1 编写redis配置类
@Configuration
@EnableCaching
public class RedisConfiguration {
	/**
     * 注入 RedisConnectionFactory
     */
    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    /**
     * 实例化 RedisTemplate 对象
     */
    @Bean
    public RedisTemplate<String, Object> functionDomainRedisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式
     */
    private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setConnectionFactory(factory);
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {

        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
    }

    //redis监听过期事件
    @Bean
    RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        // 监听所有库的key过期事件
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}
2 处理业务时拿到一个预期完成时间startTime
//将过期时间放入redis进行处理 用于处理超期未完成
        if (startTime != null) {
            //预期完成时间减去当前时间就是还剩多长时间过期
            long timeout = startTime.toEpochSecond() - ZonedDateTime.now().toEpochSecond();
            String key = Constant.ORDER_KEY_PREFIX + Order.getId();
            redisTemplate.opsForValue().set(key, 1);
            log.info("订单key:{}已放入redis,过期时间为:{}", key, timeout);
            //设置过期时间
            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
        }
3 处理过期监听时间
@Service
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

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

    @Autowired
    private OrderService orderService;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * @param message
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 拿到key
        log.info("监听Redis key过期,key:{}", message.toString());
        if (message.toString().contains(Constant.ORDER_KEY_PREFIX)) {
            String str = message.toString().substring(0, message.toString().lastIndexOf(":"));
            String orderId = message.toString().substring(str.length() + 1, message.toString().length());
            log.info("订单任务id:{}已过期", orderId);
            //根据id查询出这个订单
            Order one = orderService.findOne(Long.parseLong(orderId));
            if (Objects.isNull(one)) {
                log.info("订单任单id不存在:{}", orderId);
                return;
            }
            //超过过期时间还是未处理  变更任务状态 超期未处理
            if (Constant.TASK_STATUS_STRING_PENDING.equals(one.getTaskStatus())) {
                Order Order = new Order();
                Order.setId(Long.parseLong(orderId));
                Order.setTaskStatus(String.valueOf(3));
                Order.setUpdateDate(ZonedDateTime.now());
                Order.setUpdateUser(SecurityHxUtils.getCurrentUserId());
                orderService.update(Order);
            }
            //处理其他业务过期事件...
        }else if (message.toString().contains(Constant.OTHER_KEY_PREFIX)){
            //业务逻辑同上...
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值