RabbitMQ学习-队列数据同步

queue data sync

Posted by zwtisme on April 1, 2019

介绍RabbitMQ镜像集群中,镜像队列的数据同步规则。

概要

镜像队列

集群的队列创建后默认只在一个节点上,当集群配置为镜像集群时,队列会被镜像到所有节点上。消息发布到信道后,会被投递到主队列及镜像队列中。一个镜像队列包含一个主队列(master)和多个从队列(slave)。

image

非同步队列

rabbitmq中同步(synchronised)是用来表示master和slave之间的数据状态是否一致的。如果slave包含master中的所有message,则这个slave是synchronised;如果这个slave并没有包含所有master中的message,则这个slave是unsynchronised。

image

何时出现非同步队列

新节点加入

当新slave加入到镜像队列时,此时新slave是空的,而master中这时可能已有消息。假设这时master包含了10条消息,当第11条消息被添加到这个镜像队列中,新slave会从第11条消息开始接收。这时新slave就是unsynchronised状态。如果前10条消息从镜像队列中被消费掉了, 新slave会自动变成synchronised状态。

旧节点重新加入

当节点由于异常关闭或其他情况重启加入集群后,如果节点内有消息,那么节点就是unsynchronised状态。当出现如下情况(同样也适用于新节点加入),slave会变成synchronised状态:

  • master消息数为0
  • master中旧有的消息被消费完

疑问:旧节点重新加入后,可用消息会显示为master的,此时旧节点状态可能还是未同步,内部处理机制是否是未同步的节点,是不提供服务的吗?

选主模式

理论上越早加入的slave节点,状态越有机会是同步的,所以rabbitmq通过这种方式选主。当master出现异常因消失时,最老的slave(状态需要为已同步)被提升成master。

同步模式

在设置集群策略时,可使用【ha-sync-mode】参数来控制使用手动同步(manual)还是自动同步(automatic),默认为手动同步。

手动

如果镜像队列被设置成manual模式,当一个slave加入或重新加入队列时的行为,队列会根据消息情况来决定是否为同步状态,否则就为未同步状态。当然也可通过命令来进行同步。

#手动同步队列
[root@DEV-mHRO64 redis]# rabbitmqctl sync_queue queue_name

自动

如果镜像队列被设置成automatic模式,当一个新slave加入或已有slave重新加入时,slave会自动同步master中的所有消息,在所有消息被同步完成之前,队列的所有操作都会被阻塞(blocking)。

区别

  • manual:不保证数据可靠性,在某些情况下可能会丢失消息,但是保证了队列的可用性
  • automatic:提高了数据的可靠性,但是当有新slave加入时,可能会出现队列的暂时不可用

同步测试

针对上面不同的同步场景,进行相应的测试。

新节点加入

手动模式

原有节点情况,队列中包含2条消息

image

新加入一个节点,因为原先队列有消息,所以新slave为未同步状态

image

队列中还在不断的增加消息

image

当队列中旧消息消费后,新slave变为同步状态

image

自动模式

原有节点情况,队列中包含2条消息

image

新加入一个节点,rabbitmq执行自动同步(阻塞队列使用),所以新slave为同步状态

image

image

旧节点重新加入

手动模式

原有节点情况,队列中包含2条消息,总共有3个队列

image

某个节点由于各种原因停止服务了,只有2个队列了

image

队列中还在不断的消费消息

image

当节点重新加入到集群后,为未同步状态

image

队列中还在不断的消费消息与增加消息,当队列中旧消息消费后,节点变为同步状态

image

image

自动模式

原有节点情况,队列中包含2条消息,总共有3个队列

image

某个节点由于各种原因停止服务了,只有2个队列了

image

队列中还在不断的消费消息

image

当节点重新加入到集群后,自动进行同步,为同步状态

image

选主测试

原有节点情况,rabbit@DEV-HROEx64为master节点。

image

将原有master节点关闭,rabbit@DEV-mHRO64切换为master节点。

image

在启动rabbit@DEV-HROEx64节点,此节点变成了slave节点。

image

Tips:未同步的slave是不能选为master的,如果不存在已同步的slave,则队列将不能使用。

参考资料