当前位置: 首页>后端>正文

使用redisson实现订单过期自动取消功能

参考:
1、(41条消息) redisson延迟队列解决延迟任务_Fly_Camel_Yu的博客-CSDN博客_redission 延迟任务
2、Redisson延迟队列RDelayedQueue的使用 - 灰信网(软件开发博客聚合) (freesion.com)
3、(41条消息) Redis通过Redisson实现延迟队列(含源码)_普通网友的博客-CSDN博客_redisson延迟队列实现原理
4、(41条消息) 多线程之BlockingQueue中 take、offer、put、add的一些比较_wei_ya_wen的博客-CSDN博客_blockingqueue offer

引入:

<dependency>
     <groupId>org.redisson</groupId>
     <artifactId>redisson-spring-boot-starter</artifactId>
     <version>3.11.4</version>
</dependency>

步骤:

1、创建bean对象

/**
 * @author seeklife
 * @date 2022年08月03日 14:54
 */
@Configuration
public class SynthesisResultDelayConfig {

    @Autowired
    private RedissonClient redissonClient;

    @Bean("blockQueue")
    public RBlockingDeque<SynthesisResultQryDto> getBlockQueue() { //取延迟任务
        RBlockingDeque<SynthesisResultQryDto> blockingDeque =
                redissonClient.getBlockingDeque("prompter:synthesis:task:result");
        return blockingDeque;
    }


    @Bean("delayedQueue")
    public RDelayedQueue<SynthesisResultQryDto> getDelayQueue() { //存延迟任务
        RBlockingDeque<SynthesisResultQryDto> blockingDeque = getBlockQueue();
        RDelayedQueue<SynthesisResultQryDto> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        return delayedQueue;
    }

}

2、自定义对象,实现Serializable接口

/**
 * @author seeklife
 * @date 2022年08月03日 15:15
 */
@Data
@AllArgsConstructor
public class SynthesisResultQryDto implements Serializable {
    private String msg;
    private String type;
}

3、自己的业务逻辑

/**
 * @author seeklife
 * @date 2022年08月03日 15:18
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RedissonDelayService<T> {

    @Autowired
    private GhOrderService ghOrderService;

    @Autowired
    private OrderService orderService;


    @Async
    public void accept(SynthesisResultQryDto qryDto) {
        log.info("accept 查询订单 结果已出,msg:{}", qryDto.getMsg());
        //执行到期业务逻辑
        switch (DelayEnum.toType(qryDto.getType())){ //根据枚举匹配对应的业务逻辑执行
            case ORDER_OUTTIME_UNPAY:
                GhOrder order = ghOrderService.lambdaQuery()
                        .eq(GhOrder::getOrderNo, qryDto.getMsg()).one();
                if(ObjectUtil.isNotNull(order)
                        && order.getStatus().equals(OrderStatusEnum.ORDER_STATUS_0.getValue())){
                    orderService.cancelOrder(order.getOrderNo(), "", order.getUserId());
                }
                break;
        }
    }


}

/**
 * @author seeklife
 * @date 2022年08月03日 15:22
 */
@Slf4j
@Component
public class SynthesisResultDelayJob {

    @Autowired
    private RedissonDelayService<SynthesisResultQryDto> synthesisResultConsumer;

    @Autowired
    private RBlockingDeque<SynthesisResultQryDto> blockingDeque;

    @PostConstruct
    public void listen() {
        new Thread(() -> {
            while (true) {
                try {
                    log.info("延时队列的数量:{}", blockingDeque.size());
                    log.info("listen 本次监听时间:{}", DateUtil.formatDate(new Date()));
                    SynthesisResultQryDto dto = blockingDeque.take(); //到期时自动取出
                    log.info("listen 从队列中获取需要查询结果的延时任务信息:{}", JSON.toJSONString(dto));
                    synthesisResultConsumer.accept(dto);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

}

4、需要延迟的地方,第二个参数为时间,第三个参数选择单位分钟,秒等。

@Autowired
private RDelayedQueue<SynthesisResultQryDto> delayedQueue;

delayedQueue.offer(new SynthesisResultQryDto(orderNo,DelayEnum.ORDER_OUTTIME_UNPAY.getValue()), 30, TimeUnit.MINUTES);

集成时出现了一个问题记录一下:

问题一:
启动服务时报错,一看是springsecurity的过滤器链存在两个实现类,我在想我引入redisson和springsecurity有啥关系?

Description:

Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
    - requestMappingHandlerMapping: defined by method 'requestMappingHandlerMapping' in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]
    - controllerEndpointHandlerMapping: defined by method 'controllerEndpointHandlerMapping' in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.class]

解决办法:
1、还原还没引入redisson时的状态,发现启动成功。猜想还是出在依赖问题上,看看有没冲突。
引入时排除一下。

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.11.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-actuator</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

问题二:
redisson简单使用--内存溢出异常:o.redisson.client.handler.CommandsQueue [153] : Exception - 掘金 (juejin.cn)


https://www.xamrdz.com/backend/3c51939156.html

相关文章: