赞
踩
采用disc,则需要对exchange,queue,delivery mode 设置成durable模式。
好处:当RabbitMQ失效了,message仍然可以在重启之后恢复。
-record(msg_location,{ msg_id, //消息ID
ref_count, //引用计数
file, //消息存储的文件名
offset, //消息在文件中的偏移量
total_size //消息的大小
}).
-record(file_summary,{ file, //文件名
valid_total_size, //文件有效数据大小
left, //位于该文件左边的文件
right, //位于该文件右边的文件
file_size, //文件总的大小
locked, //上锁标记 垃圾回收时防止对文件进行操作
readers //当前读文件的队列数
})
上面X表示无效数据。
根据 #file_summary{} 中left,right找逻辑上相邻的两个文件,并且两个文件的有效数据可在一个文件中存储
将右边的文件删除。
Erlang进程之间并不共享内存(binaries类型除外),而是通过消息传递来通信,每个进程都有自己的进程邮箱。
Erlang默认没有对进程邮箱大小设限制,所以当有大量消息持续发往某个进程时,会导致该进程邮箱过大,最终内存溢出并崩溃。
在RabbitMQ中,如果生产者持续高速发送,而消费者消费速度较低时,如果没有流控,很快就会使内部进程邮箱大小达到内存阈值,阻塞生产者(得益于block机制,并不会崩溃)。然后RabbitMQ会进行page操作,将内存中的数据持久化到磁盘中。
为了解决该问题,RabbitMQ使用了一种基于信用证的流控机制。用流控(Flow Control)机制来确保稳定性。
上述就是RabbitMQ的多层队列结构的设计,我们可以看出从Q1到Q4,基本经历RAM->DISK->RAM这样的过程。
总结
消息被消费的速度 大于等于 接收新消息的速度,对于不需要保证可靠不丢的消息极可能只会有Alpha状态。
对于durable=true的消息,它一定会进入gamma状态,若开启publish confirm机制,只有到了这个阶段才会确认该消息已经被接受,若消息消费速度足够快,内存也充足,这些消息也不会继续走到下一状态。
消息被消费的速度 小于 接收新消息的速度,这些消息就会进入到很深的队列中去,增加处理每个消息的平均开销。
因为要花更多的时间和资源处理"积压"的消息,所以用于处理新来的消息的能力就会降低,使得后来的消息又被积压进入很深的队列,继续加大处理每个消息的平均开销,这样情况就会越来越恶化,使得系统的处理能力大大降低。
根据官网资料,应对这一问题,有三个措施:
1. 进行流量控制。
2. 增加prefetch的值,即一次发送多个消息给接收者,加快消息被消费掉的速度。
3. 采用multipleack,降低处理ack带来的开销。
负责消息的广播
负责master上的回调处理
对于Basic.Publish,消息同时发送到master和所有slave上,如果此时master宕掉了,消息还发送slave上,这样当slave提升为master的时候消息也不会丢失。
GM模块实现的一种可靠的组播通讯协议,该协议能够保证组播消息的原子性,即保证组中活着的节点要么都收到消息要么都收不到。
# 查看那些slaves已经完成同步
rabbitmqctl list_queues
# 手动的方式同步一个queue
rabbitmqctl sync_queue name
# 取消某个queue的同步功能
rabbitmqctl cancel_sync_queue name
在rabbitmq中同步(synchronised)是用来描述master和slave之间的数据状态是否一致的。
当一个新slave加入到一个镜像队列时,这时这个新slave是空的,而master中这时可能包含之前接收到的消息。假设这时master包含了N条消息,当第N+1条消息被添加到这个镜像队列中,这个新slave会从这个第N+1条消息开始接收。
由RabbitMQ的slave加入和重新加入队列的方式,我们得出一个结论,越早加入队列的slave,越有更大的机会是同步状态的,所以RabbitMQ通过下面方式选主
RabbitMQ通过参数配置的方式,在可用性和数据可靠性做出了一定的权衡。
# 手工(munual)同步命令
rabbitmqctl sync_queue name
当一个新slave加入时,slave会自动同步master中的所有消息,在所有消息被同步完成之前,所有的操作都会被阻塞(blocking),会出现队列的暂时不可用。
在所有情况下,master关闭时,RabbitMQ可以把一个非同步的slave提升成新的master。
RabbitMQ的镜像队列机制是将queue镜像到cluster中其他的节点之上。
在通常的用法中,针对每一个镜像队列都包含一个master和多个slave,分别位于于不同的节点。slave会准确地按照master执行命令的顺序进行命令执行,故slave与master上维护的状态应该是相同的。
所有动作都只会向master发送,然后由master将命令执行的结果广播给slave们,故看似从镜像队列中的 消费操作 实际上是在master上执行的。
在该实现下,如果镜像队列中的一个master失效了,集群自动选出一个slave(最老的slave)提升为master,此后message可以继续发送到队列上。
因为每个操作在所有节点都要做一遍。
因为exclusive队列是连接独占的,当连接断开,队列自动删除。所以实际上这两个参数对exclusive队列没有意义。
比如是通过rabbitmqctl stop命令停止或者优雅关闭OS,那么slave不会接管master,也就是说此时镜像队列不可用
不论master因为何种原因停止,slave都会接管master,优先保证可用性。
客户端Basic.Publish操作,消息会同步到所有节点(master和所有slave),如果此时master宕掉了,消息还发送slave上,这样当slave提升为master的时候消息也不会丢失
除了与slave相连的客户端连接全部断开之外,没有其他影响。
如果此时所有slave处于未同步状态,则未同步部分消息丢失
该场景下可能是由掉电等原因造成,只需在30s内连续启动A和B即可恢复镜像队列。
offline参数允许rabbitmqctl在离线节点上执行forget_cluster_node命令,迫使RabbitMQ在未启动的slave节点中选择一个作为master。
无法处理
官网文档
http://www.rabbitmq.com
RabbitMQ 队列镜像配置主机挂掉之后自动切换 另一台
http://blog.csdn.net/csethcrm/article/details/53928313
RabbitMQ不同Confirm模式下的性能对比
http://ju.outofmemory.cn/entry/177937
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。