基于Redisson的超时订单关闭方案

1.引入redisson

2.添加redisson的配置

在这里插入图片描述

3.创建配置类RedissonConfig

在这里插入图片描述

4、封装 Redis 延迟队列工具类

@Slf4j
@Component
public class RedisDelayQueueUtil {
	@Autowired
	private RedissonClient redissonClient;

    /**
     * 添加延迟队列
     *
     * @param value     队列值
     * @param delay     延迟时间
     * @param timeUnit  时间单位
     * @param queueCode 队列键
     * @param <T>
     */
    public <T> void addDelayQueue(T value, long delay, TimeUnit timeUnit, String queueCode) {
        try {
            RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);
            RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
            delayedQueue.offer(value, delay, timeUnit);
            log.info("(添加延时队列成功) 队列键:{},队列值:{},延迟时间:{},单位:{}", queueCode, value, delay,timeUnit);
        } catch (Exception e) {
            log.error("(添加延时队列失败) {}", e.getMessage());
            throw new RuntimeException("(添加延时队列失败)");
        }
    }

    /**
     * 获取延迟队列
     *
     * @param queueCode
     * @param <T>
     * @return
     * @throws InterruptedException
     */
    public <T> T getDelayQueue(String queueCode) throws InterruptedException {
        RBlockingDeque<Map> blockingDeque = redissonClient.getBlockingDeque(queueCode);
        T value = (T) blockingDeque.take();
        return value;
    }
}

5、创建业务枚举类

@Getter
public enum RedisDelayQueueEnum {

	ORDER_PAYMENT_TIMEOUT("ORDER_PAYMENT_TIMEOUT","超时订单自动关闭队列", "orderPaymentTimeout"),
 
	/**
	 * 延迟队列 Redis Key
	 */
	private String code;
 
	/**
	 * 中文描述
	 */
	private String name;
 
	/**
	 * 延迟队列具体业务实现的 Bean
	 * 可通过 Spring 的上下文获取
	 */
	private String beanId;

}

6.定义延迟队列执行器

/**
 * 延迟队列执行器
 */
public interface RedisDelayQueueHandle<T> {
 
	void execute(T t);
 
}

7、创建枚举中定义的Bean,并实现延迟队列执行器 OrderTimeout:超时订单延迟队列处理类

/**
 * 订单支付超时处理类
 */
@Component
@Slf4j
public class OrderTimeout implements RedisDelayQueueHandle<Map> {
	@Override
	public void execute(Map map) {
		log.info("(收到超时订单延迟消息) {}", map);
		// TODO 订单相关,处理业务逻辑...
		1.调用第三方(微信,支付宝)的支付接口,查询订单是否已经支付,如果确认没支付则,调用关闭订单支付的api,并修改订单的状态为关闭,同时回滚库存数量。
		2.如果支付状态为已支付则需要做补偿操作,修改订单的状态为已支付,订单历史记录
 
	}
}

8、创建延迟队列消费线程,项目启动完成后开启

/**
 * 启动延迟队列
 */
@Slf4j
@Component
public class RedisDelayQueueRunner implements CommandLineRunner {
 
	@Autowired
	private RedisDelayQueueUtil redisDelayQueueUtil;
    @Autowired
    private ThreadPoolTaskExecutor threadPool;
   ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 50, 30, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(1000), Executors.defaultThreadFactory());
	@Override
	public void run(String... args) {
		threadPool.execute(() -> {
			while (true){
				try {
					RedisDelayQueueEnum[] queueEnums = RedisDelayQueueEnum.values();
					for (RedisDelayQueueEnum queueEnum : queueEnums) {
						Object value = redisDelayQueueUtil.getDelayQueue(queueEnum.getCode());
						if (value != null) {
							RedisDelayQueueHandle redisDelayQueueHandle = SpringUtil.getBean(queueEnum.getBeanId());
							redisDelayQueueHandle.execute(value);
						}
					}
				} catch (InterruptedException e) {
					log.error("(Redis延迟队列异常中断) {}", e.getMessage());
				}
			}
		}).start();
		log.info("(Redis延迟队列启动成功)");
	}
}

9.测试

/**
 * 延迟队列测试
 */
@RestController
public class RedisDelayQueueController {
 
	@Autowired
	private RedisDelayQueueUtil redisDelayQueueUtil;
 
	@PostMapping("/addQueue")
	public void addQueue() {
		Map<String, String> map1 = new HashMap<>();
		map1.put("orderId", "10001");
		map1.put("remark", "订单支付超时,自动取消订单");
 
		// 为了测试效果,延迟10秒钟
		redisDelayQueueUtil.addDelayQueue(map1, 10, TimeUnit.SECONDS, RedisDelayQueueEnum.ORDER_PAYMENT_TIMEOUT.getCode());
	}	 
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值