RabbitMQ 消息状态

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RabbitMQ 消息状态相关的知识,希望对你有一定的参考价值。

参考技术A 消息的位置:消息是保存在内存或磁盘上的;
消息是有索引的,索引的位置也是在内存或磁盘上的;
同一时刻可能内存和磁盘中都有消息或索引.
这些场景是根据队列类型来决定的.
在rabbit中,队列中的消息可能会处理以下四种状态:
alpha:消息内容以及消息在队列中的位置(消息索引)都保存在内存中;
beta:消息内容只在磁盘上,消息索引只在内存中;
gamma:消息内容只在磁盘上,消息索引在内存和磁盘上都存在;
delta:消息的内容和索引都在磁盘上。
——对于持久化消息,消息内容和消息索引都必须先保存在磁盘上,然后才处于上述状态中的一种。即属性是Durable的消息.
通过状态的流转来实现消息位置的变化,目的是在时间和空间中做出合理的取舍.
从内存个CPU的角度来理解就是满足不同的内存和CPU需求。
alpha最耗内存,但很少消耗CPU,因为直接存储在内存中;
delta基本不消耗内存,但是要消耗更多的CPU以及磁盘I/O操作(delta需要两次I/O操作,一次读索引,一次读消息内容, 所以消息尽可能的发送完立刻被消费;
beta及gamma只需要一次I/O操作来读取消息内容)。
gamma更多的是持久化的消息出现的状态。

在队列的状态vqstate(参见 [$RABBIT_SRC/src/rabbit_variable_queue.erl])结构中,存在q1,q2,delta,q3,q4五个队列(使用 q1~q4使用Erlang的queue模块,delta存储结构依赖于消息索引的实现),其中q1,q4只包含alpha状态的消 息,q2,q3只包含beta和gamma状态的消息,delta包含delta状态的消息。
一般情况下消息会以q1->q2->delta->q3->q4的顺序进行状态变换:消息进入队列时,处于alpha状态并保存 在内存中(q1或q4),然后某个时刻发现内存不足,被转换到beta状态(q2,q3)(这时候其实有两个转换 q1->q2,q4->q3),如果还是内存不足,被转换到delta状态(delta)(q2->delta,q3->delta);当从队 列中消费消息时,会先从处于alpha状态的内存队列(q4)中获取消息,如果q4为空,则从beta状态的队列 (q3)中获取消息,如果q3也为空,则会从delta状态的消息队列中读取消息,并将之转移到q3。
上述步骤只是个一般步骤,实际运行时,中间的步骤都是可以跳过的,比如消息可能在一开始被放在q4队列 中、q1队列中的元素会直接跳到q4队列中(这两种情况下,q3,delta,q2队列都为空);当delta队列为空 时,q2队列可以直接跳到q3队列,q1队列也可以直接跳到q3。

RabbitMQ系统中队列进程中消息流动逻辑 1.publish(消息的插入)
如果Q3队列为空,则将消息放入Q4队列,如果Q3队列不为空,则将消息放入Q1队列 2.alpha类型的消息转化为beta类型的消息(将消息的内容存入磁盘文件)(push_alphas_to_betas函数)
(1).Q1队列的转化,如果磁盘文件中的消息数量为0,则将Q1中的消息写入Q3队列,如果磁盘文件中的 消息数量不为0,则将Q1中的消息写入Q2队列
(2).Q4队列的转化,从Q4队列末端将消息放入到Q3队列的末端 3.beta类型的消息delta类型的消息(push_betas_to_deltas函数)
(1).从Q3队列末端将消息的队列索引存入磁盘文件
(2).将Q2队列中的消息的队列索引存入磁盘文件 4.如果Q4,Q3中的消息为空,且磁盘文件中有消息,则将从磁盘中读取消息,会将delta类型的消息转化为 beta类型的消息
(1).如果读取一个队列索引磁盘文件后磁盘文件中已经没有消息,则先将读取到的消息存入Q3队列末 尾,然后将Q2队列中的消息存入Q3队列的末尾
(2).如果读取一个队列索引磁盘文件后的磁盘文件中还有消息,则将读取到的消息存入Q3队列末尾

以上是关于RabbitMQ 消息状态的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 消息状态

RabbitMQ RabbitMQ高级特性

RabbitMQ RabbitMQ高级特性

Python实现RabbitMQ中6种消息模型

Kafka和RabbitMQ有哪些区别,各自适合什么场景?

Python消息队列(RabbitMQ)