当前位置:   article > 正文

RabbitMQ小结_rabbitmq暂停消费后,当前这条消息还会消费么

rabbitmq暂停消费后,当前这条消息还会消费么
1、解耦,异步,削峰

可以将rabbitMQ看做是一个菜鸟驿站或者蜂巢,在以前的送快递和取快递时,是一个同步进行的事情,快递员打电话给客户,让客户拿快递;快递员在等客户,而客户在去拿快递的路上,是同步进行的,而在双十一的时候,大量的快递会让快递员崩溃;而菜鸟驿站的出现,就使得快递员与客户减少了交流,快递员和客户只需要分别在菜鸟驿站进行交易实际,实现解耦;同时,客户可以在不同的时间内进行拿快递,就实现了异步,最后在双十一的时候,快递员只需要将一个地区的快递放置在一个菜鸟驿站,节省了快递员的大部分时间,实现了削峰;

2、重要概念

生产者(Producer):发送消息的应用。
消费者(Consumer):接收消息的应用。
队列(Queue):存储消息的缓存。
消息(Message):由生产者通过RabbitMQ发送给消费者的信息。
连接(Connection):连接RabbitMQ和应用服务器的TCP连接。
通道(Channel):连接里的一个虚拟通道。当你通过消息队列发送或者接收消息时,这个操作都是通过通道进行的。
交换机(Exchange):交换机负责从生产者那里接收消息,并根据交换类型分发到对应的消息列队里。要实现消息的接收,一个队列必须到绑定一个交换机。
绑定(Binding):绑定是队列和交换机的一个关联连接。
路由键(Routing Key):路由键是供交换机查看并根据键来决定如何分发消息到列队的一个键。路由键可以说是消息的目的地址。

3、如何保证RabbitMQ不被重复消费?

在消费生产时,MQ内部针对每条生产者发送的消息生成一个 inner-msg-id,作为去重和幂等的依据,避免重复的消息进入队列,在消费者消费时,要求消息体中必须要有一个bizid作为去重和幂等的依据,避免同一条消息被重复消费

4、如何保证RabbitMQ消息的可靠传输(如何解决丢数据的问题)?

丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息;
生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息;
transaction机制就是说:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。然而,这种方式有个缺点:吞吐量下降;
confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

消息队列丢数据:消息持久化。
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。
那么如何持久化呢?
将queue的持久化标识durable设置为true,则代表是一个持久的队列
发送消息的时候将deliveryMode=2
这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据

消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可!
启用手动确认模式可以解决这个问题
①自动确认模式,消费者挂掉,待ack的消息回归到队列中。消费者抛出异常,消息会不断的被重发,直到处理成功。不会丢失消息,即便服务挂掉,没有处理完成的消息会重回队列,但是异常会让消息不断重试。
②手动确认模式,如果消费者来不及处理就死掉时,没有响应ack时会重复发送一条信息给其他消费者;如果监听程序处理异常了,且未对异常进行捕获,会一直重复接收消息,然后一直抛异常;如果对异常进行了捕获,但是没有在finally里ack,也会一直重复发送消息(重试机制)。
③不确认模式,acknowledge=“none” 不使用确认机制,只要消息发送完成会立即在队列移除,无论客户端异常还是断开,只要发送完就移除,不会重发。

5、如何确保消息正确地发送至RabbitMQ?

RabbitMQ使用发送方确认模式,确保消息正确地发送到RabbitMQ。
发送方确认模式:将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(not acknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

6、如何确保消息接收方消费了消息?

接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。
下面罗列几种特殊情况:
如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要根据bizId去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。

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

轮询: 默认的策略,消费者轮流,平均地接收消息
公平分发: 根据消费者的能力来分发消息,给空闲的消费者发送更多消息

8、消息如何被优先消费

x-max-priority

9、无法被路由的消息去了哪里?

无设置的情况下,无法路由(Routing key错误)的消息会被直接丢弃
解决方案:
将mandatory设置为true,并配合ReturnListener,实现消息的回发
声明交换机时,指定备份的交换机

 Map<String,Object> arguments = new HashMap<String,Object>();
 arguments.put("alternate-exchange","备份交换机名");
  • 1
  • 2
10、消息基于什么传输?

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

11、交换器类型(4种交换器类型)

Direct Exchange: 直连交换器
小结:直连交换器发送消息会根据路由和交换机的绑定关系发送到队列
如果交换器名称为"",将使用默认交换器
默认交换器不会绑定任何队列,mq会直接把route_key当做queue名称去查找
Fanout Exchange: 分发交换器(扇出交换器)
小结: 分发交换器发送消息会分发至所有和其有绑定的队列中,这样消息会被多个消费者处理
Topic Exchange: 主题交换器
小结:主题交换器可以让每个队列只接收它关注的信息
Headers Exchange: 头信息交换器(了解)
头信息交换器可以实现更为复杂的匹配但性能不好,
不推荐使用,了解即可

12、工作模式(常用5种)

简单模式:
消息只有一个消费者
使用默认交换器即可(direct)
工作队列模式:
消息有多个消费者,消息只可以被消费一次
使用默认交换器即可(direct)
发布订阅模式:
消息有多个消费者,而且消息会被多个消费者同时消费
使用分发交换器即可(fanout)
路由模式:
根据路由的key,将消息发送到指定的队列
使用直接交换器即可(direct)
通配符(主题)模式:
根据路由的key,进行通配符匹配,发送到指定的队列(topic)
使用主题交换器即可

13、过期时间TTL

第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。
第二种方法是对消息本身进行单独设置,每条消息的TTL可以不同。
如果两种方法一起使用,则消息的TTL以两者之间较小的那个数值为准。
//设置TTL

Map<String, Object> argss = new HashMap<>();
argss.put("x-message-ttl", 6000);
channel.queueDeclare(QUEUE_NAME, true, false, false, argss);
  • 1
  • 2
  • 3
14、死信队列

可以称之为死信交换器,也有人称之为死信邮箱。当消息在一个队列中变成死信( dead message)之后,它能被重新被发送到另一个交换器中,这个交换器就是DLX,绑定DLX的队列就称之为死信队列。
消息被拒绝(Basic. Reject/Basic.Nack),并且设置requeue参数为false;
消息过期;
队列达到最大长度。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/694416
推荐阅读
相关标签
  

闽ICP备14008679号