RBBITMQ存储机制

 

消息读取时:在读取消息的时候,先根据消息的ID Cmsg id) 找到对应存储的文件,如果文件存在并
且未被锁住,则直接打开文件,从指定位置读取消息的内容。如果文件不存在或者被锁住了,
则发送请求由rabbit_msg_store 进行处理。

 

消息删除时:消息的删除只是从ETS 表删除指定消息的相关信息, 同时更新消息对应的存储文件的相关信息。执行消息删除操作时,井不立即对在文件中的消息进行删除,也就是说消息依然在文件中,仅仅是标记为垃圾数据而己。当一个文件中都是垃圾数据时可以将这个文件删除。当检测到前后两个文件中的有效数据可以合并在一个文件中,井且所有的垃圾数据的大小和所有文件(至少有3 个文件存在的情况下〉的数据大小的比值超过设置的阑值GARBAGE FRACTION (默认值为0.5) 时才会触发垃圾回收将两个文件合井

删除:前后两个有逻辑关联消息存储文件,x代表已标记删除的消息
前文件:X->D->X->C-X->B-A
后文件:G->X->X->F->X->X-E
将后文件没标记清除的消息合并到前文件中
前文件:G->F->E->D->C->B->A
然后删除后文件

 

 

队列的结构:rabbit _amqqueue_ process 和backing_ queue组成的

rabbit _amqqueue_ process:负责协议相关的消息处理,即接收生产者发布的消息、向消费
者交付消息、处理消息的确认(包括生产端的confirm 和消费端的ack) 等

backing queue:是消息存储的具体形式和引擎,并向rabbit amqqueue process 提供相关的接口以供调用。

if 消息投递的队列为空,并且有消费者订阅该队列的消息,消息会直接交给消费者消费,不会入队

if 消息无法直接投给消费者是,消息暂时投入目的消息队列,一边重新投递,消息入队列后,不是一直不变的,会随系统的负载一直流动,消息状态一直发生变化

4中消息状态:主要作用是满足不同的内存和CPU 需求

alpha: 消息内容(包括消息体、属性和headers) 和消息索引都存储在内存中。(最耗内存,最少消耗cup)
beta: 消息内容保存在磁盘中,消息索引保存在内存中。(一次I/O操作从rabbit_msg_store 读取消息)
 gamma: 消息内容保存在磁盘中,消息索引在磁盘和内存中都有。(一次I/O操作从rabbit_msg_store 读取消息)
delta: 消息内容和索引都在磁盘中。(几乎不消耗内心,耗更多的CUP资源和磁盘I/O操作(读取消息两次I/O操作,一次是读消息索引(从rabbit queue index 中), 一次是读消息内容(从rabbit_msg_store 中))

对于持久化的消息,消息内容和消息索引都必须先保存在磁盘上,才会处于上述状态中的
一种。而gamma 状态的消息是只有持久化的消息才会有的状态。   

 

 

什么情况下会消息会发生状态转移呢:

RabbitMQ在运行中,会根据统计消息传送速度定期计算当前内存能保存的消息最大数据量:(target_ram_count)值,

如果alpha状态下消息数量> target_ram_count值,多余的消息会发生状态转移

对于普通没有优先级或者镜像对列来说:backing_queue 默认实现是:rabbit_variable_ queue,

其内部通过5 个子队列 流转顺序:Q1->Q2->Delta->Q3->Q4

Q1:(只包含alpha 状态的消息) 、

Q2:(包含beta 和
gamma 状态的消),

Delta:(只包含delta 状态的消息)

Q3: (包含beta 和
gamma 状态的消息)和

Q4:(只包含alpha 状态的消息) 来体现消息
的各个状态

消息读取时:从Q4开始读取,为null,则从Q3读取,为null时,则返回队列是null的,如果Q3不为空,则取出Q3的消息,判断Q3与Delta的长度,如果都为空,进而判断Q2,Delta,Q3,Q4都为空,将Q1的消息转移到Q4,下次直接从Q4 中获取消息,如果Q3为null,Delta不为null,则将Delta 的消息转移至Q3 中,下次可以直接从Q3 中获取消息。

在将消息从Delta 转
移到Q3 的过程中, 是按照索引分段读取的,首先读取某一段,然后判断读取的消息的个数与
Delta 中消息的个数是否相等,如果相等,则可以判定此时Delta 中己无消息,则直接将Q2 和
刚读取到的消息一并放入到Q3 中:如果不相等,仅将此次读取到的消息转移到Q3 0

 

负载压力大的时候:解决消息入队太深积压的:

(1)增加prefetch_count 的值,即一次发送多条消息给消费者, 加快消息被消费的速度

(2) 采用multiple ack ,降低处理ack 带来的开销

(3)流量控制

 

 

 

惰性队列:

 

rabbitmq3.6.0引入了lazy queue,目的就是消息直接存入磁盘中,为了支持更长的队列,支持更多的消息存储。

在消息者长时间没有消费消息(比如消费者下线,宕机,维护关闭)造成的消息堆积,适合lazy queue。

 

默认情况下,消息会竟可能存在内存中以便消费者快速的消费掉,即使durable=true的持久化消息也会在内存中保持一份备份,

当rabbitmq释放内存是会将内存的消息换页到磁盘中,会消耗很长时间,会阻塞队列操作,无法接受新的消息入队

 

惰性队列会将接收到的消息直接存入文件系统中,而不管是持久化的或者是非持久化的,
这样可以减少了内存的消耗,但是会增加1/0 的使用,如果消息是持久化的,那么这样的1/0
操作不可避免,惰性队列和持久化的消息可谓是"最佳拍档"。注意如果惰性队列中存储的是非
持久化的消息,内存的使用率会一直很稳定,但是重启之后消息一样会丢失。

 

通过channel .qu eueDeclare声明队列的模式(如果队列已经存在会先删除):两种:lazy和default 

Map<String ,Object> args=new HashMap<String Object>();

agrs.put("x-queue-mode","lazy");

channel. queueDeclare( "myqueue" , false , false , false , args);

 

对应的Policy 设置方式为:优先级会高于声明式
rabbitmqctl set_policy Lazy " ^myqueue$ " ' {"queue-mode ":" lazy" } ' --apply-to queues

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值