【064期】面试官问:RabbitMQ 本身不支持延迟队列,那么如何实现?

最后

本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们:

目录:

二面蚂蚁金服(交叉面),已拿offer,Java岗定级阿里P6

Java面试核心知识点

一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!

二面蚂蚁金服(交叉面),已拿offer,Java岗定级阿里P6

Java面试核心知识点

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取


队列中可以设置两个属性:

  • x-dead-letter-exchange

  • x-dead-letter-routing-key

当这个队列里面的消息成为死信之后,就会投递到x-dead-letter-exchange指定的exchange中,其中带着的routing key就是中指定的值x-dead-letter-routing-key。Java精选面试题,内涵3000+道高级面试题,点击即可进入(微信搜索:Java精选面试题,也可以),支持在线随时刷题。

而如果使用默认的exchange(routing key就是希望指定的队列),则只需要把x-dead-letter-exchange设置为空(不能不设置),类似下面

死信消息的路由则会根据x-dead-letter-routing-key所指定的进行路由,如果这个值没有指定,则会按照消息一开始发送的时候指定的routing key进行路由

Dead-lettered messages are routed to their dead letter exchange either:

with the routing key specified for the queue they were on; or, if this was not set, with the same routing keys they were originally published with.

例如,如果一开始你对exchange X发送消息,带着routing key “foo”,进入了队列 Q然后消息变死信后,他会被重新发送到 dead letter exchange ,其中发给dead letter exchange带着的routing key 还是foo。但如果这个队列Q本身是设置了x-dead-letter-routing-key bar, 那么他发送到 dead letter exchange的时候,带着的routing key 就是bar。Java精选面试题,内涵3000+道高级面试题,点击即可进入(微信搜索:Java精选面试题,也可以),支持在线随时刷题。

需要注意的是,当死信消息重新路由到新的队列的时候,在死信目标队列确认收到这条死信消息之前,原来队列的消息是不会删除的,也就是说在某些异常场景下例如broker突然shutdown,是有机会存在说一个消息既存在于原队列,又存在于死信目标队列。具体可参考官方说明:

Dead-lettered messages are re-published with publisher confirms turned on internally so, the “dead-letter queues” (DLX routing targets) the messages eventually land on must confirm the messages before they are removed from the original queue. In other words, the “publishing” (the one in which messages expired) queue will not remove messages before the dead-letter queues acknowledge receiving them (see Confirms for details on the guarantees made). Note that, in the event of an unclean broker shutdown, the same message may be duplicated on both the original queue and on the dead-lettering destination queues.

Time-To-Live(TTL)


开头我们说过,实现延迟队列除了用死信消息外,还需要利用消息过期的TTL机制,因为只要消息过期了,就会触发死信。

RabbitMQ有两种方法让设置消息的TTL:

直接在消息上设置

byte[] messageBodyBytes = “Hello, world!”.getBytes();

AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()

.expiration(“60000”)

.build();

channel.basicPublish(“my-exchange”, “routing-key”, properties, messageBodyBytes);

为队列设置消息过期TTL

注意,队列还有一个队列TTL,x-expires,这个的意思是队列空置经过一段时间(没有消费者,没有被重新声明,没有人在上面获取消息(basic.get))后,整个队列便会过期删除,不要混淆

如果同时设置了消息的过期和队列消息过期属性,则取两个较小值。

设计延迟队列:


例如,我们需要触发一个推送新闻,30分钟后统计这个新闻的下发情况,我们就需要一个延迟队列,新闻推送后,往延迟队列发送一个消息,这个队列的消息在30分钟后被消费,这时候触发即可统计30分钟的下发情况。我们可以这样设计:

定义一个正常的队列:ARRIVAL_STAT,统计程序监听此队列,进行消费。

定义一个“延迟队列”(RabbitMQ没有这样的队列,这里只是人为的制造一个这样的队列):DELAY_ARRIVAL_STAT,其中设置好对应的x-dead-letter-exchange,x-dead-letter-routing-key。为了简单说明,我使用默认的exchange,那么配置如下:

x-dead-letter-exchange=“”

x-dead-letter-routing-key=“ARRIVAL_STAT”

意思是,消息当这个队列DELAY_ARRIVAL_STAT的消息变死信之后,就会带着routing key “ARRIVAL_STAT”发送默认的空exchange,即队列ARRIVAL_STAT。

并且这个队列不能有消费者消费消息。

这样我们就实现了消息的死信转发。下一步,只需要让消息在这个DELAY_ARRIVAL_STAT在30分钟后过期变死信即可。按照上文所说,有两种方法,我们可以为队列的消息设置30分钟TTL,或者发送消息的时候指定消息的TTL为30分钟即可。Java精选面试题,内涵3000+道高级面试题,点击即可进入(微信搜索:Java精选面试题,也可以),支持在线随时刷题。

示例如下:

“延迟队列”的堵塞缺陷


由于设置了x-dead-letter-exchange的队列本身也是普通队列,其过期的顺序是按照队列头部顺序的过期的。也就是说,如果你队列头的消息A过期时间是5分钟,后面对这个队列发送消息B的带着过期时间1分钟,那么后面的队列B要等队列A过期了才会触发过期:

最后

这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档

祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!

感谢大家的支持!!

image.png

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

需要这份系统化的资料的朋友,可以点击这里获取

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ可以通过插件的方式实现延迟队列。以下是一种常用的方法: 1. 首先,确保你的RabbitMQ服务器已经安装了rabbitmq_delayed_message_exchange插件。如果没有安装,你需要先安装该插件。 2. 创建一个延迟队列,你可以使用如下代码声明一个延迟队列: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() args = { 'x-delayed-type': 'direct', } channel.exchange_declare(exchange='delayed_exchange', exchange_type='x-delayed-message', arguments=args) channel.queue_declare(queue='delayed_queue') channel.queue_bind(queue='delayed_queue', exchange='delayed_exchange', routing_key='routing_key') ``` 3. 发送延迟消息到延迟队列,你可以使用如下代码发送延迟消息: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() properties = pika.BasicProperties(headers={'x-delay': 5000}) # 设置延迟时间,单位为毫秒 channel.basic_publish( exchange='delayed_exchange', routing_key='routing_key', body='Hello, delayed message!', properties=properties ) ``` 4. 消费延迟队列中的消息,你可以使用如下代码消费延迟消息: ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() def callback(ch, method, properties, body): print("Received delayed message:", body) channel.basic_consume(queue='delayed_queue', on_message_callback=callback, auto_ack=True) channel.start_consuming() ``` 以上是通过插件实现延迟队列的方法,你可以根据自己的需求进行调整和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值