RabbitMQ知识点总结

本文介绍了RabbitMQ的基本概念,包括消息队列的作用、消息路由方式,如fanout、direct和topic交换器。讨论了消息如何变为死信以及如何保证消息不丢失,涉及持久化、生产者和消费者端的策略。同时阐述了如何处理消息顺序消费和避免重复消费的问题。
摘要由CSDN通过智能技术生成

什么是 rabbitmq

采用 AMQP 高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦

消息队列的作用与使用场景

异步:批量数据异步处理(批量上传文件)
削峰:高负载任务负载均衡(电商秒杀抢购)
解耦:串行任务并行化(退货流程解耦)
广播:基于Pub/Sub实现一对多通信

消息如何路由?

消息 -> 交换器 -> 队列,消息携带Routing-key至交换器。交换器根据交换器的路由规则和交换器和队列的Binding-key绑定关系,将消息路由至指定的队列。常见的交换器的路由规则有3种:

  1. fanout:如果交换器收到消息,将会广播到所有绑定的队列上
  2. direct:如果路由键完全匹配,消息就被投递到相应的队列
  3. topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符

多个消费者监听一个队列时,消息如何分发

  1. 轮询,默认的策略,消费者轮流,平均地接收消息
  2. 公平分发,根据消费者的能力来分发消息,给空闲的消费者发送更多消息
//当消费者有x条消息没有响应ACK时,不再给这个消费者发送消息
	channel.basicQos(int x)

消息在什么时候会变成死信

  1. 消息拒绝并且没有设置重新入队
  2. 消息过期
  3. 消息堆积,并且队列达到最大长度,先入队的消息会变成DL

死信 queue 可用于排查 message 被 reject 或 undeliver 的原因。

消息如何被优先消费

//生产者
 Map<String, Object> argss = new HashMap<String, Object>();
        argss.put("x-max-priority",10);

//消费者
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .priority(5) // 优先级,默认为5,配合队列的 x-max-priority 属性使用

如何自动删除长时间没有消费的消息

// 通过队列属性设置消息过期时间
        Map<String, Object> argss = new HashMap<String, Object>();
        argss.put("x-message-ttl",6000);

 // 对每条消息设置过期时间
        AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .expiration("10000") // TTL

消息基于什么传输

由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。

RabbitMQ上的一个queue中存放的message是否有数量限制?

可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处 理效率的下降。

普通集群模式下,若cluster中拥有某个queue的owner node失效了,且该queue 被声明具有durable属性,是否能够成功从其他node上重新声明该 queue ?

不能,在这种情况下,将得到404 NOT_FOUND错误。只能等queue所 属的node恢复后才能使用该queue。但若该queue本身不具有durable 属性,则可在其他node上重新声明。

routing_key和binding_key的最大长度是多少?

255字节

如何确保证消息不丢失

1. 持久化

消息持久化,当然前提是队列必须持久化。

RabbitMQ确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到持久交换器上时,Rabbit会在消息提交到日志文件后才发送响应。
一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ会在持久化日志中把这条消息标记为等待垃圾收集。如果持久化消息在被消费之前RabbitMQ重启,那么Rabbit会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列。

2. 生产者端

rabbitTemplate.setConfirmCallback()回调方法,检测消息是否成功发送到Exchange。ack=true成功,为保证消息的可靠传输,这里可以记录消息的状态为已发送成功;ack=false失败,为保证不丢失消息,这里可以将未成功发送的消息记录下来,起异步任务重新发送。

rabbitTemplate.setMandatory(true)+rabbitTemplate.setReturnCallback()这两项一起设置,检测消息是否从Exchange路由到Queue。这是一个失败回调, 只有消息从Exchange路由到Queue失败才会回调这个方法,为保证不丢失消息,这里可以将未成功发送的消息记录下来,查看消息被丢弃的原因;不设置的话,找不到路由队列的消息会被直接丢弃;

生产者确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

3. 消费者端

spring.rabbitmq.listener.simple.acknowledge-mode=manual,设置mq消费消息手动确认。

当消费者成功消费一条消息之后,channel.basicAck(long deliveryTag, boolean multiple),进行手动ack,然后mq才会将此条消息从队列中删除。注意,如果消费者忘记手动ack,则消息会一直滞留在mq,大bug;这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性;

如果消费者处理消息失败,channel.basicNack(long deliveryTag, boolean multiple, boolean requeue),消费者发送nack,可以指定消息是否requeue重新入队列;

下面罗列几种特殊情况:

  • 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
  • 如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,占用消费者的Qos, 将不会给该消费者分发更多的消息。

如何确保证消息顺序消费

从根本上说,异步消息是不应该有顺序依赖的。在MQ上估计是没法解决。要实现严格的顺序消息,简单且可行的办法就是:保证生产者 - MQServer - 消费者是一对一对一的关系。

如果有顺序依赖的消息,要保证消息有一个hashKey,类似于数据库表分区的的分区key列。可以根据这个hashKey对消息进行分组,使得具有依赖关系的消息具有相同的hashKey,路由至同一个队列,然后单个consumer消费保障消息的顺序消费。具体方法有:

  1.  在生产者端,根据消息的hashKey进行分组,确保有依赖关系的消息分到同一个组。每个组对应一个 queue ,一个 consumer 消费一个 queue,使得消息顺序消费;
  2.  在消费者端,消息全部路由到一个 queue,一个consumer 先把所有的消息接收,然后这个 consumer 内部用内存队列根据消息的hashKey对消息做分组排队,然后起多线程来消费不同内存队列中的消息;

如何规避消息重复消费

1. 消息消费的业务逻辑实现幂等性,消息多次消费业务结果保持一直;

2. 通过业务 messageId 作为消息的标识,如果消息已经消费过,同一个ID消息在此到来时直接丢弃消息;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RabbitMQ是一种消息队列(MQ)系统,它具有多个相关概念和模式。其中一些重要的知识点包括: 1. RabbitMQ的四大概念:生产者、消费者、交换机和队列,它们一起构成了消息传递的基本组成部分。 2. RabbitMQ的六种模式:简单模式、工作模式、轮询分发、消息应答、自动应答和手动应答。 3. RabbitMQ持久化消息:可以将消息持久化到磁盘上,以防止消息在RabbitMQ发生故障时丢失。 4. 死信队列:当消息因某些原因无法被消费时,可以将其发送到死信队列中进行处理。 5. 延迟队列:可以设置消息的延迟时间,使其在一定时间后被消费。 6. 发布确认:可以通过发布确认机制来确保消息被成功发送到RabbitMQ。 7. RabbitMQ集群:可以通过搭建集群来实现高可用性和负载均衡。 8. 幂等性:消息的幂等性指的是多次处理同一消息不会产生副作用。 9. 优先级队列:可以为消息设置优先级,以确保高优先级的消息能够更快地被消费。 10. 惰性队列:惰性队列指的是只有在需要时才会被创建。 这些是RabbitMQ的一些重要知识点,它们可以帮助我们更好地理解和应用RabbitMQ。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [RabbitMQ 知识点总结](https://blog.csdn.net/PaperJack/article/details/124734987)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [RabbitMQ知识点](https://blog.csdn.net/weixin_42100694/article/details/113514641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值