rabbitmq 集群数据存储与单点故障

为什么80%的码农都做不了架构师?>>>   hot3.png

rabbitmq每个节点记录四类信息:交换机、队列、绑定、vhost元数据。

集群中的信息存储

在rabbitmq2.6.0之前没有镜像队列,数据存储情况为:

队列所属节点保存队列全部信息(元数据、状态、内容),其他节点拥有队列元数据;所有节点保存exchange、bundling信息。好处有两点:

    1.节约存储空间,每个节点都有相同信息的拷贝,意味着磁盘空间成倍占用;

    2.提升性能,数据在节点间同步占用网络资源,如果是持久化状态,又会有大量I/O;

正常情况的工作原理:

集群中有三个节点:rabbit、hare、hare1,队列声明在hare节点,向rabbit节点发消息,消息会转发到hare节点,消费者连接hare1节点,则从hare节点读取数据。

异常情况1(发送过程中故障):

向rabbit节点发送5条消息,第一条发送成功后,关掉hare节点

2017-11-16 12:05:07,015 [http-bio-8080-exec-1] 
[org.springframework.amqp.rabbit.core.RabbitTemplate]-[DEBUG] Publishing message (Body:'< publish
 message 内容为:[ Thu Nov 16 12:05:07 CST 2017 ]>' MessageProperties [headers={}, 
contentType=text/plain, contentEncoding=UTF-8, contentLength=62, deliveryMode=PERSISTENT, priority=0, deliveryTag=0])on exchange [AMC_TMP_EXCHANGE], routingKey = [cluster.send]

控制台显示正常发送,实际上后面4条消息已经丢失

localhost:sbin zcjlq$ ./rabbitmqctl -n hare stop_app
Stopping rabbit application on node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE

hare节点重启,只有第一条消息

localhost:sbin zcjlq$ ./rabbitmqctl -n hare start_app
Starting node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE	1

拓展:

如果使用publisher confirm机制,在回调函数RabbitTemplate.ConfirmCallback,你将拿到5个ack,RabbitTemplate.ReturnCallback不会被回调。


异常情况2(发送完毕故障):

假如我们连上任意节点,发送4条消息,先不消费,各个节点都能查到消息。

下面停掉队列所属节点hare

localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE	4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE	4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare stop_app
Stopping rabbit application on node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE
localhost:sbin zcjlq$ ./rabbitmqctl -n hare start_app
Starting node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE	4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE	4

我们发现:停用hare节点后,在另外两个节点查不到消息,hare节点重启后,三个节点都能查到消息。

说明:本测试在单机上启动三个节点(单机集群搭建见后续文章)

rabbitmqctl -n参数指定节点名称,-p指定vhost名称,start_app启动节点,stop_app关闭节点,

list_queues查看队列列表和待消费消息。

异常情况3(故障期间重新声明队列):

在恢复hare节点前,我们尝试通过其他节点重新创建队列。出现以下错误

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: 
#method(reply-code=404, reply-text=NOT_FOUND - home node 'hare@localhost' 
of durable queue 'AMC_TMP_QUEUE' in vhost 'zcjlq' is down or inaccessible, class-id=50, method-id=10)

 

节点类型

集群中的节点有两个类型:磁盘节点、内存节点。内存节点(ram)将所有的队列、交换器、绑定、用户、权限、vhost的元数据定义都仅存储于内存中。磁盘节点(disc)将元数据存储在磁盘中。

是磁盘节点还是内存节点?

在集群中声明队列、交换器、绑定的时候,其他节点会得到元数据的同步,如果集群中全都是磁盘节点,那么你需要等到所有的节点都磁盘I/O后才完成工作,内存节点将会更快。

rabbitmq要求集群中至少有一个磁盘节点。磁盘节点离开集群时,集群还可以进行部分工作,创建队列、创建交换机、创建绑定、添加用户、更改权限、添加或删除集群节点将不能使用。原理的磁盘节点重启后,集群可以正常工作。我们想要更安全一点:原磁盘节点重启前,为让集群正常工作,这时候可以考虑设置两个集群节点,当其中一个磁盘节点离开时,它会将该变更通知到至少一个磁盘节点。

 

转载于:https://my.oschina.net/zcjlq/blog/1574455

你可能感兴趣的:(rabbitmq 集群数据存储与单点故障)