RabbitMQ(四)队列结构

一、队列结构

通常队列由两部分组成:
1、AMQQueue,负责AMQP协议相关的消息处理,即接收生产者发布的消息、向消费者投递消息、处理消息confirm、acknowledge等等
2、BackingQueue,它提供了相关的接口供AMQQueue调用,完成消息的存储以及可能的持久化工作等。
BackingQueue又由5个子队列组成:Q1, Q2, Delta, Q3和Q4。
 
二、在BackingQueue中消息的状态
RabbitMQ中的消息一旦进入队列,不是固定不变的,它会随着系统的负载在队列中不断流动,消息的不断发生变化。
有如下4个状态:
1、Alpha:消息的内容和消息索引都在RAM中。Q1和Q4的状态。
2、Beta:消息的内容保存在DISK上,消息索引保存在RAM中。Q2和Q3的状态。
3、Gamma:消息内容保存在DISK上,消息索引在DISK和RAM都有。Q2和Q3的状态。
4、Delta:消息内容和索引都在DISK上。Delta的状态。
 
对于持久化的消息,消息内容和消息所有都必须先保存在DISK上,才会处于上述状态中的一种,而Gamma状态的消息是只有持久化的消息才会有的状态。
 
 
三、消息的流动
如果消息投递的目的队列是空的,并且有消费者订阅了这个队列,那么该消息会直接发送给消费者,不会经过队列这一步。
当消息无法直接投递给消费者时,需要暂时将消息存入队列,以便重新投递。
进入队列的消息,一般会按照Q1->Q2->Delta->Q3->Q4的顺序进行流动,但是并不是每条消息都一定会经历所有的状态,这个取决于当前系统的负载状况。
引起消息流动主要有两方面因素:
1、消费者获取消息
2、由于内存不足引起消息换出到磁盘
 
四、内存不足导致的消息流动
在运行时,RabbitMQ会根据消息传递的速度定期计算一个当前内存中能够保存的最大消息数量(target_ram_count),如果alpha状态的消息数量大于此值,则会引起消息的状态转换,多余的消息可能会转换到beta、gama或者delta状态。
 
五、消费引起的消息流动
消费者获取消息也会引起消息的状态转换。
当消费者获取消息时,
1、从Q4中获取消息,如果获取成功则返回。
2、如果Q4为空,则尝试从Q3中获取消息,系统首先会判断Q3是否为空,如果为空则返回队列为空,即此时队列中无消息。
3、如果Q3不为空,则取出Q3中的消息,进而再判断此时Q3和Delta中的长度,如果都为空,则可以认为 Q2、Delta、 Q3、Q4 全部为空,此时将Q1中的消息直接转移至Q4,下次直接从 Q4 中获取消息。
4、如果Q3为空,Delta不为空,则将Delta的消息转移至Q3中,下次可以直接从Q3中获取消息。
在将消息从Delta转移到Q3的过程中,是按照索引分段读取的,首先读取某一段,然后判断读取的消息的个数与Delta中消息的个数是否相等,如果相等,则可以判定此时Delta中己无消息,则直接将Q2和刚读取到的消息一并放入到Q3中,如果不相等,仅将此次读取到的消息转移到Q3。

在系统负载较高时,消息若不能很快被消费掉,这些消息就会进入到很深的队列中去,这样会增加处理每个消息的平均开销。
因为要花更多的时间和资源处理“堆积”的消息,如此用来处理新流入的消息的能力就会降低,使得后流入的消息又被积压到很深的队列中,继续增大处理每个消息的平均开销,继而情况变得越来越恶化,使得系统的处理能力大大降低。

原文地址:https://www.cnblogs.com/guoxianqi2020/p/13994836.html