Skip to content

02-RabbitMQ高级特性 ​

消息确认 ​

这里的消息确认是队列到消费者之间的确认,而不是生产者到队列之间的确认。生产者到队列之间的确认叫作发布确认

机制 ​

由于接收到消息只有两种状态:正常接收和异常接收。因此消息确认针对这两个有不同的处理结果

  • ACK: 告诉队列已经正常接收到了,让队列可以把原本的消息给丢弃了
  • NACK: 告诉队列消息接收/处理异常,可以通过传入相关的参数控制重新发送相关的参数

这些都是手动确认的情况下才可以实现,如果是自动确认,那么就没有相关的配置了

但是在 Java 中是分为三个机制:

  • NONE: 这个是表示什么都不操作,接收到就直接丢弃
  • AUTO: 这个是没有异常就是自动 ACK,如果有异常,那么就自动发送 NACK
  • MANUAL: 手动操作,无论是否有异常,都由程序员设定

Java 这三个机制是站在自己的视角下面的,

  • none 不操作 -> 那就只能让 RabbitMQ 自动确认了
  • auto 自动 -> 有异常重新发送,没异常自动执行其他逻辑
  • manual 手动 -> 把控制权交还给程序员

持久化 ​

01-快速入门-RabbitMQ核心概念
01-快速入门-RabbitMQ核心概念

在消息的传输过程中,可能会在这三个地方出现问题:

  1. 在生产者到 RabbitMQ 的服务端
  2. RabbitMQ 服务端
  3. RabbitMQ 服务端到消费者

在 1 和 3 这两个情况,可以使用发布确认和消息确认这两个机制来保证传输的可靠性。而第 2 个这个情况,就是要使用持久化来保障了

持久化还可以分为三块:交换机持久化,队列持久化和消息持久化。

  • 消息持久化:就是把消息设置为持久化,如果想要消息持久化,那么队列也必须要持久化

交换机持久化和队列持久化这里就不说了,因为之前的就已经设置过了

发布确认 ​

发布确认
发布确认
发布确认是分为 confirm 模式和 return 模式
  • confirm: 处理生产者到交换机之间的关系
  • return: 处理交换机到队列之间的关系

重试机制 ​

如果是网络波动导致的问题,采用重试是很不错的一个解决方案,但是如果是代码导致的问题,那么多次重复是无法解决问题的,因此配置重试的次数/时间是一个很有必要的选择了

TTL ​

RabbitMQ 设置 TTL 有两个地方可以设置,设置消息的 TTL 和设置队列的 TTL, 消息的 TTL 是仅仅针对这一个消息,而队列是针对所有的进入这个队列的消息。

一个消息的 TTL 是取决于队列的 TTL 和消息本身的 TTL 的较小值

回收机制 ​

队列的 TTL 是可以通过判断队首元素来判断当前是否是消息是否过期,但是消息的 TTL 是不能判断的,如果每一次判断都遍历一次队列,那么性能就太低了。

消息的 TTL 是在要被消费之前才会判断,因此这就可能会产生已经过期但依然占用资源的内容(比如第一次发送的 TTL 为 30s 第二次发送 5s),这个也叫做死信

死信 ​

死信
死信
死信是指那些由于某一些原因,导致相关的消息无法被消费,这些消息就是称为死信。

死信常见的几个场景:

  1. TTL 过期了
  2. 消息被消费了,但是是 nack, 并且没有被重新入队
  3. 队列满了,消息进入后被丢弃了

延迟队列 ​

延迟队列是把消息延期交给消费者消息。比如会议在 10:00 召开,那么就可以提前 30 分钟发送消息。

但是有点遗憾的是,在 RabbitMQ 中没有直接可以配置的延迟队列,需要通过 死信队列+TTL 配合,才能实现延迟队列

如果是使用队列的 TTL 那么是没有什么问题的,但是如果是使用消息的 TTL,在后来的消息先过期的情况下,会导致延迟出现问题(消息积压)

这个问题可以通过插件来解决:(注意版本号要配对, 4.1.x 就配对 4.1.x 的插件)

事务 ​

事务这个概念在 MySQL 里面就已经讲述过了,这里就不讲述了,概念很简单。

限流 ​

顾名思义,限流就是限制流量,把处理消息的速度控制在一定的范围内。

通过限流,我们可以防止服务器因为突然的高并发而宕机,也可以实现负载均衡这样的策略

这个限流的大小是要看具体业务+机器等条件综合考虑的,一般是通过压力测试获取到它的最大值