当前位置: 首页 > 图灵资讯 > 技术篇> 实现过期订单的关闭

实现过期订单的关闭

来源:图灵教育
时间:2023-05-19 09:09:36

常用方式

  1. Redission
  2. RabitMQ插件
  3. RabitMQ私信队列
  4. RocketMQ延迟消息
  5. Redistzset
  6. Redis过期监控
  7. kafka时间轮
  8. 定时任务
  9. Nettty时间轮
  10. JDK自带DelayQueueue (延迟队列)
  11. 被动关闭
不同的方案也适用于不同的场景:
  • 自己玩:被动关闭
  • 单个应用,业务量不大:Nettty的时间轮,JDK自带的DelayQueueue、定时任务
  • 分布式应用,业务量小:Redis过期监控,RabitMQ死信队列,Rediszset、定时任务
  • 业务量大、并发性高的分布式应用:Redission、RabitMQ插件,kafka时间轮,RocketMQ延迟消息
Redission

Redison是一个基于Redis的框架,它不仅提供了一系列常用的分布式Java对象,还提供了许多分布式服务。

分布式延迟队列RDelayedQueue是在Redision中定义的,这是一个基于我们之前介绍的zset结构的延迟队列,允许元素以指定的延迟时间放入目标队列。

事实上,基于内存的延迟队列是在zset的基础上添加的。当我们想向延迟队列添加数据时,redission将数据+超时间放入zset中,并启动延迟任务。当任务到期时,我们将在zset中取出数据并返回给客户端。

大致思路是这样的,感兴趣的人可以看看RDelayedQueue的具体实现。

RabitMQ插件

事实上,基于Rabitmq,可以在没有死信队列的情况下实现延迟消息,即基于Rabitmq_delayed_message_exchange插件可以解决通过死信队列延迟消息的消息堵塞问题。但是这个插件来自RabitMQ的3.6.12开始支持,所以对版本有要求。

官方插件:

实现过期订单的关闭_定时任务

然而,基于插件的方式,消息不会立即进入队列,而是将其保存在基于Erlang开发的Mnesia数据库中,然后通过定时器查询需要交付的消息,然后交付给x-delayed-在message队列中。

基于RabitMQ插件的方式可以实现延迟消息,没有消息堵塞的问题,但由于它是基于插件的,插件支持的最大延长时间是(2^32)-1 毫秒,大约49天,超过这个时间会立即消费。但是他是基于RabbitMQ实现的,所以可用性和方便性都很好

RocketMQ延迟消息

与Kafka相比,RocketMQ具有支持延迟消息的强大功能。

延迟消息,当消息写入Broker时,消费者不会立即消费,消费者需要等待指定的时间才能处理,称为延迟消息。

有了延迟消息,我们可以在订单创建后发送延迟消息,如20分钟取消订单,然后发送延迟20分钟,然后20分钟后,消息将被消费者消费,消费者收到消息后,关闭订单。

然而,RocketMQ的延迟消息并不支持任何时间的延迟,它只支持:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h这几个时间。(商业版支持任何时间)

可以看出,在RocketMQ延迟消息之后,我们的处理要简单得多。我们只需要发送消息和接收消息,系统完全解耦。但由于延迟消息的时间有限,它不是很灵活。

如果我们的业务中关闭订单的时间与RocketMQ延迟信息支持的时间相匹配,则可以基于RocketMQ延迟信息实现。否则,这种方法不是最好的。

kafka时间轮

由于基于Netty的时间轮存在一些问题,是否实现了其他时间轮?

有些是Kafka的时间轮。Kafka有许多延迟操作,如延迟生产、延迟提取、延迟数据删除等。这些延迟功能由内部延迟操作管理器专门处理,底部由时间轮实现。

而且,为了解决一些时间跨度大的延迟任务,Kafka 还引入了层次时间轮,可以更好地控制时间粒度,处理更复杂的定时任务处理场景;

Kafka 中间时间轮的实现是 TimingWheel 类,位于 kafka.utils.timer 包里。基于Kafka的时间轮也能得到O(1)时间复杂度,性能还是不错的。

基于Kafka时间轮的实现方式有点复杂,需要依靠Kafka,但其稳定性和性能更高,适合分布式场景。

上一篇:

Java面向对象之构造方法

下一篇:

java 锁