订单超时 取消订单 的几种实现方案总结与对比

4 篇文章 1 订阅
3 篇文章 0 订阅

开场白:老铁们对于文章有错误、不准确,或需要补充的请留言讨论 ,大家共同学习。如果觉得还不错的请关注、留言、点赞 、收藏。 创作不易,且看且珍惜

场景 :

在开发中,往往会遇到一些关于延时任务的需求。例如:生成订单 30 分钟未支付,则自动取消;生成订单 60 秒后,给用户发短信。

方案

此处就涉及到 延时任务定时任务 等问题。
这里只说 方案 思路 和 优缺点,代码不做实现。

序号方案是否推荐思路优点缺点
1quartz(定时任务 轮询)最不推荐
存在延迟
用quartz 定时去扫描订单 查询过期简单 快捷 易行,业务小的可以考虑 支持集群操作(1)对服务器内存消耗大
(2)时效性差,存在延迟,比如你每隔 3 分钟扫描一次,那最坏的延迟时间就是 3 分钟
(3)效率低。假设你的订单有几千万条,每隔几分钟这样扫描一次,数据库损耗极大 (4)可能重复执行。如果第一次轮询耗时长,第二次轮询又开始了,会造成任务重复执行
(5)占用数据库资源,对数据库的压力比较大
2JDK 的延迟队列 (DelayQueue )不推荐 利用 JDK 自带的 DelayQueue 来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入 DelayQueue 中的对象,是必须实现 Delayed 接口的。效率高,任务触发时间延迟低。(1)服务器重启后,数据全部消失,怕宕机
(2)集群扩展相当麻烦
(3)因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常
(4)代码复杂度较高
3时间轮算法不推荐创建环形队列,例如可以创建一个包含3600个slot的环形队列(本质是个数组)。任务集合,环上每一个slot是一个Set,同时启动一个timer,这个timer每隔1s,在上述环形队列中移动一格,有一个Current Index指针来标识正在检测的slot无需再轮询全部订单,效率高。任务触发时间延迟时间比 delayQueue 低,代码复杂度比 delayQueue 低。 一个订单,任务只执行一次。时效性好,精确到秒(控制timer移动频率可以控制精度)。服务器重启后,数据全部消失,怕宕机。集群扩展相当麻烦。一直占用服务器资源、性能,因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现 OOM 异常
4redis zset 缓存不推荐 利用 redis 的 zset,zset 是一个有序集合,每一个元素(member)都关联了一个 score,通过 score 排序来取集合中的值重启或宕机 会丢失数据 (有人会说redis持久化 ,redis最大优点 ,持久化会降低性能,就算持久化停机、宕机也会丢失一段时间的数据,具体不过多说。)存在一个致命的硬伤,在高并发条件下, 会出现多个线程消费同一个资源的情况
(解决方案:
(1)用分布式锁,但是用分布式锁,性能下降了,该方案不细说。
(2)对 ZREM 的返回值进行判断,只有大于 0 的时候,才消费数据,于是将 consumerDelayMessage() 方法里的:)
5redis键空间机制(Keyspace Notifications)一般 利用该机制可以在 key 失效之后,提供一个回调,实际上是 redis 会给客户端发送一个消息。是需要 redis 版本 2.8 以上。(1)由于使用 Redis 作为消息通道,消息都存储在 Redis 中。如果发送程序或者任务处理程序挂了,重启之后,还有重新处理数据的可能性。
(2)做集群扩展相当方便
(3)时间准确度高
(1)需要额外进行 redis 维护。
(2)Redis的发布/订阅目前是即发即弃(fire and forget)模式的,因此无法实现事件的可靠通知。也就是说,如果发布/订阅的客户端断链之后又重连,则在客户端断链期间的所有事件都丢失了。此方案不是太推荐,当然,如果你对可靠性要求不高,可以使用
6MQ : rabbitmq死信队列一般 我们可以采用 RabbitMQ 的延时队列。RabbitMQ 具有以下两个特性,可以实现延迟队列。
(1) RabbitMQ 可以针对 Queue 和 Message 设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为 dead letter
。(2) lRabbitMQ的 Queue 可以配置 x-dead-letter-exchange 和 x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了 deadletter,则按照这两个参数重新路由。结合以上两个特性,就可以模拟出延迟消息的功能。
高效,可以利用 rabbitmq 的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性本身的易用度要依赖于 rabbitMq 的运维。因为要引用 rabbitMq,所以复杂度和成本变高
7MQ : rocketmq延迟队列推荐监听mq的延迟消息,一旦接收到就处理简单、高效、扩展性强,消息支持持久化增加了可靠性在RocketMQ开源版本中,支持延迟消息,但是不支持任意时间精度的延迟消息,只支持特定级别的延迟消息。消息延迟级别分别为1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h,共18个级别。如果我们想把关闭订单时间设置在15分钟该如何处理呢?显然不够灵活
8MQ : RabbitMQ的delay插件rabbitmq_delayed_message_exchange实现延时消息推荐去RabbitMQ的官网下载插件,插件地址:https://www.rabbitmq.com/community-plugins.html,直接搜索rabbitmq_delayed_message_exchange即可找到我们需要下载的插件,下载和RabbitMQ配套的版本。简单、高效,通过安装插件,自定义交换机,让交换机拥有延迟发送消息的能力,从而实现延迟消息。与 rabbitmq 死信队列对比:由于死信队列方式需要创建两个交换机(死信队列交换机+处理队列交换机)、两个队列(死信队列+处理队列),而延迟插件方式只需创建一个交换机和一个队列,所以后者使用起来更简单。本身的易用度要依赖于 rabbitMq 的运维。因为要引用 rabbitMq,所以复杂度和成本变高
  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值