定时轮询,DelayQueue,ZSet,TTL+DLX(建议收藏)

简介: 定时轮询,DelayQueue,ZSet,TTL+DLX(建议收藏)

业务场景

我们买火车票或者叫外卖的时候,下完单之后会跳转到支付页面,页面里通常会有一个计时器,要求在指定时间内完成支付,否则订单就会被自动取消。这就是延时任务的一个典型业务场景。分析这个场景,其实最关键的就是如何在订单超时的时候立即触发取消订单的动作。

那么如何实现这种延时业务呢?通常有以下4种方案。

定时任务轮询db

用户下单后db中会生成一条订单记录,记录了订单号、用户ID、创建时间、订单详情、订单状态等信息。假设超时时间是600秒,我们后台起一个定时任务,每隔固定时间运行一次,每次扫描db中的超时订单select * from order where createTime <= now()-600,然后取消查询到的订单。

这种方法实现简单,但是有很多缺点。超时时间通常是秒级的,如果定时任务每秒运行一次,那么就相当于每秒就要对订单表做一次扫描,这是相当消耗db资源的操作,因此定时任务一般不会设置为秒级;但是如果设置为分钟级,又会牺牲即时性,比如600秒超时,很有可能660秒的时候订单才被取消。

DelayQueue

JDK的DelayQueue(延迟队列)是无界阻塞队列,只有在延迟期满时才能从中获取元素。每生成一个订单,在把订单记录到db的同时,要把订单id等信息投递到延迟队列中去,队列会按照超时时间进行排序,最先超时的订单排在队列的头部;起一个单独的线程不断地从队列中摘取元素然后去做取消订单的动作。

这种方法最大的缺点就是没有将超时信息持久化,服务重启之后延迟队列的元素不会被恢复。

redis的zset

在redis中创建一个key是”delayOrders”的zset,每个member就是订单ID,member的score就是该订单的超时时间戳。我们每次从zset中取出score最小也就是最先超时的元素,判断其是否超时,如果超时就将其从zset中删除并取消订单,如果未超时就继续执行下一次循环。

RabbitMQ的TTL+DLX

RabbitMQ可设置消息过期时间(TTL),当消息过期后可以将该消息投递到队列上设置的死信交换器(DLX)上。然后投递到死信队列中,重新消费。

image.png

四种方案对比

image.png

相关文章
|
3月前
|
消息中间件 数据库
七、延时队列
七、延时队列
41 0
|
4月前
|
Java 测试技术
TTL的CRR操作
TTL的CRR操作
75 0
|
6月前
|
消息中间件 Java
RabbitMQ之ttl(过期消息)解读
RabbitMQ之ttl(过期消息)解读
|
9月前
|
消息中间件
死信队列和延迟队列的介绍
死信队列和延迟队列的介绍
|
Java 数据库
定时任务还在用数据库轮询?redission延时队列了解一下
在平常的开发中经常会碰到定时任务处理的场景,比如说用户进行商品购买,下单之后超过半个小时还未进行支付则自动取消该笔订单,订单支付状态由待支付变更为已支付;
定时任务还在用数据库轮询?redission延时队列了解一下
|
消息中间件 JSON 数据库
rabbitMQ延时队列与TTL和DLX、延迟队列的相关介绍
TTL是Time To Live的缩写, 也就是生存时间。 RabbitMq支持对消息和队列设置TTL,对消息这设置是在发送的时候指定,对队列设置是从消息入队列开始计算, 只要超过了队列的超时时间配置, 那么消息会自动清除。 如果两种方式一起使用消息的TTL和队列的TTL之间较小的为准,也就是消息5s过期,队列是10s,那么5s的生效。 默认是没有过期时间的,表示消息没有过期时间;如果设置为0,表示消息在投递到消费者的时候直接被消费,否则丢弃。
|
消息中间件 JSON 数据库
rabbitMQ延时队列与TTL以及DLX和死信队列简单介绍
TTL是Time To Live的缩写, 也就是生存时间。 RabbitMq支持对消息和队列设置TTL,对消息这设置是在发送的时候指定,对队列设置是从消息入队列开始计算, 只要超过了队列的超时时间配置, 那么消息会自动清除。 如果两种方式一起使用消息的TTL和队列的TTL之间较小的为准,也就是消息5s过期,队列是10s,那么5s的生效。 默认是没有过期时间的,表示消息没有过期时间;如果设置为0,表示消息在投递到消费者的时候直接被消费,否则丢弃。
|
消息中间件
死信队列 和消息TTL过期代码
先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer将消息投递到broker或者直接到queue里了,consumer从queue取出消息进行消费,但某些时候由于特定的原因导致queue中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。
死信队列 和消息TTL过期代码
|
消息中间件
面试官:RabbitMQ过期时间设置、死信队列、延时队列怎么设计?
本文讲解如何设计RabbitMQ过期时间设置、死信队列、延时队列,希望对大家有所帮助。
247 0
面试官:RabbitMQ过期时间设置、死信队列、延时队列怎么设计?
延时队列的使用
队列中的数据如何才能更好的去使用,一直存在困惑。使用场景也有些模糊,还在摸索中。有问题就留言吧,一起学习