订单过期自动关闭方案

一、订单查询时检查是否要关闭

实现方式

在订单查询接口中,每次用户访问订单时,系统检查该订单是否已过期,若过期则执行关闭操作。

Java代码示例

public class OrderService {


    @Autowired
    private OrderRepository orderRepository;


    public Order getOrder(String orderId) {
        Order order = orderRepository.findById(orderId);
        if (order != null && order.isExpired()) {
            closeOrder(order);
        }
        return order;
    }


    private void closeOrder(Order order) {
        // 关闭订单逻辑,如更新数据库状态等
        order.setStatus(OrderStatus.CLOSED);
        orderRepository.save(order);
    }
}

优缺点分析

  • 优点:实现简单,无需额外开发定时任务或消息队列。

  • 缺点

    • 脏数据问题:如果用户长期不访问订单,过期订单将一直存在于数据库中。
    • 性能影响:每次查询订单都进行写操作,可能增加数据库负担。
    • 实时性差:依赖于用户访问订单的时间。

**
**

适用场景

适用于学习或小规模、实时性要求不高的系统。

二、xxl-job定时任务

实现方式

使用xxl-job等调度框架,设置定时任务定期扫描数据库中过期的订单,并执行关闭操作。

Java代码示例

@Component
public class ExpiredOrderJob {


    @Autowired
    private OrderService orderService;


    @XxlJob("closeExpiredOrders")
    public void execute() throws Exception {
        List<Order> expiredOrders = orderService.findExpiredOrders();
        for (Order order : expiredOrders) {
            orderService.closeOrder(order);
        }
    }
}


@Service
public class OrderService {


    @Autowired
    private OrderRepository orderRepository;


    public List<Order> findExpiredOrders() {
        return orderRepository.findByStatusAndExpireTimeLessThan(OrderStatus.CREATED, LocalDateTime.now());
    }


    // closeOrder方法同上
}

优缺点分析

  • 优点:实现简单,定时执行,易于管理。

  • 缺点

    • 时间不精准:基于固定频率执行,可能导致订单关闭时间晚于预期。
    • 数据库压力:大量订单时,集中扫描数据库可能对性能造成影响。
    • 分库分表问题:在分库分表环境下,全表扫描效率极低。

适用场景

适用于对时间精度要求不高、订单量适中的系统。

三、RocketMQ延迟消息

实现方式

在订单创建时,发送一个延迟消息到RocketMQ,消息延迟时间与订单过期时间一致。消息到期后,消费者接收到消息并执行关闭订单操作。

Java代码示例

@Autowired
private RocketMQTemplate rocketMQTemplate;


public void createOrderAndSendDelayMessage(Order order) {
    // 创建订单逻辑
    // ...


    // 发送延迟消息
    int delayLevel = calculateDelayLevel(order.getExpireTime()); // 根据过期时间计算延迟等级
    rocketMQTemplate.convertAndSend("delayTopic", "tag", order, message -> {
        message.setDelayTimeLevel(delayLevel);
        return message;
    });
}


@RocketMQMessageListener(consumerGroup = "orderConsumerGroup", topic = "delayTopic")
public class OrderConsumer implements RocketMQListener<Order> {


    @Autowired
    private OrderService orderService;


    @Override
    public void onMessage(Order order) {
        orderService.closeOrder(order);
    }
}

优缺点分析

  • 优点:系统解耦,延迟消息处理灵活。

  • 缺点

    • 延迟时间固定:RocketMQ支持的延迟时间有限,不够灵活。
    • 依赖外部消息队列,增加系统复杂度。

适用场景

适用于订单量较大、对时间精度有一定要求,且延迟时间能与RocketMQ支持的延迟级别匹配的场景。

四、Redis消息自动过期和notify-keyspace-events事件监听

实现方式

利用Redis的键过期特性和notify-keyspace-events事件监听功能,在redis的redis.conf里加入notify-keyspace-events的配置,开启key事件通知功能。然后订单创建时在Redis中设置一个键,并设置过期时间。在代码里要实现一个redis key过期的监听器,键过期时,监听器接收到过期事件,执行关闭订单操作。

Java代码示例

@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {


    @Autowired
    private OrderService orderService;


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


    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = message.toString();
        // 假设订单ID作为Redis键
        orderService.closeOrderById(expiredKey);
    }
}


@Service
public class OrderService {


    // closeOrderById方法根据订单ID关闭订单
}


// Redis配置(略)

优缺点分析

  • 优点

    • 实时性好:订单过期即处理。
    • 效率高:Redis性能优异。
  • 缺点

    • Redis配置复杂:需要开启notify-keyspace-events。
    • 集群部署时扩展性较差。

适用场景

适用于订单量适中、对实时性要求高、系统架构较简单的场景。

五 CaffeineCache
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()       
    .expireAfterWrite(1, TimeUnit.MINUTES)       
    .removalListener((key, value, cause) ->            
                     System.out.println("Key " + key + " expired. Do something here."))       
    .build(key -> createExpensiveGraph(key));

在这个示例中,我们创建了一个LoadingCache并设置了键的写入过期时间为1分钟。当键过期时,会触发removalListener中的操作,您可以在这里执行相应的操作。

五、总结

每种过期订单关闭方案都有其独特的优缺点和适用场景。选择哪种方案,需要根据实际业务需求、系统规模、团队技术栈以及对实时性的要求综合考虑。例如,在订单量较小、实时性要求不高的场景下,可以选择订单查询时检查;在订单量适中、对时间精度有一定要求的场景下,xxl-job定时任务是一个不错的选择;而在订单量较大、对实时性要求极高的场景下,RocketMQ延迟消息或Redis消息自动过期方案可能更为合适。总之,没有绝对的最佳方案,只有最适合当前业务场景的方案。

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值