springboot整合redis监听订单超时自动处理

还可以使用rabbitMQ延时队列来处理,相对而言,个人觉得rabbitmq处理会更加稳定,毕竟redis的监听是包括全局所有的key的,redis 产生 expired 通知的时间为过期的key被删除的时候,但是当key的生存时间为0时,redis不能保证这个key会立即被删除
先将配置文件进行修改
springboot整合redis监听订单超时自动处理_第1张图片
搜索 notify-keyspace-events 配置一下键过期的参数, 修改成下图

springboot整合redis监听订单超时自动处理_第2张图片
notify-keyspace-events前面千万千万不能留有空格,我图片那样配置后出现读取配置文件错误。 配置完需要重启一下redis的服务使配置生效

yml文件中redis的配置
springboot整合redis监听订单超时自动处理_第3张图片
配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

/**
 * 注册redisTemplate
 */
@Configuration
public class RedisConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

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

redis监听类

import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单过期监听:接收过期的redis消息,获取到key(订单号)
 * 然后去更新对应订单状态
 */
@Transactional
@Component
@Slf4j
public class RedisListener extends KeyExpirationEventMessageListener {

    @Autowired
    private ScalpOrderService scalpOrderService;

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

    /**
     *监听失效的key
     * @param message
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        //  获取失效的key
        String expiredKey = message.toString();
        String prefix = "";
        if(expiredKey.indexOf("_") != -1){
            prefix = expiredKey.substring(0,expiredKey.indexOf("_"));
        }
        //根据key的前缀判断是否属于订单过期
        if("order".equals(prefix)){
            String orderId = expiredKey.substring(expiredKey.indexOf("_") + 1);
            //业务逻辑处理
            ScalpOrder order = scalpOrderService.getById(orderId);
            //将订单状态更改为超时
            order.setOrderStatus(UsedCode.ORDER_PAST_DUE);
            scalpOrderService.updateById(order);
            //处理订单冻结信息
            scalpOrderService.putFreezeMoney(order,UsedCode.ORDER_PAST_DUE,Object->{
                log.info("订单号:{}已超时" ,expiredKey);
                return Result.ok();
            });
        }
    }
}

控制层设置订单的过期时间为30分钟

redisUtil.ins("order_"+orderId,orderId,30, TimeUnit.MINUTES);

redisUtil

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 写入缓存
     */
    public boolean ins(final String key, String value,int time,TimeUnit unit) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value,time, unit);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    public boolean expire(String key, long time) {
        try {
            if (time > 0L) {
                this.redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }

            return true;
        } catch (Exception var5) {
            var5.printStackTrace();
            return false;
        }
    }
    
    /**
     * 删除缓存
     */
    public boolean delete(final String key) {
        boolean result = false;
        try {
            redisTemplate.delete(key);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }

    }
}

测试结果

springboot整合redis监听订单超时自动处理_第4张图片

你可能感兴趣的:(springboot)