rabbitmq集群故障恢复详解

rabbitmq集群故障恢复详解

大家好,又见面了,我是全栈君。

RabbitMQ的mirror queue(镜像队列)机制是最简单的队列HA方案,它通过在cluster的基础上增加ha-mode、ha-param等policy选项,可以根据 需求将cluster中的队列镜像到多个节点上,从而实现高可用,消除cluster模式中队列内容单点带来的风险。

在使用镜像队列之前,有几点注意事项必须熟记于心(下文中将混用主节点和master,从节点和slave):

1. 镜像队列不能作为负载均衡使用,因为每个操作在所有节点都要做一遍。

2. ha-mode参数和durable declare对exclusive队列都不生效,因为exclusive队列是连接独占的,当连接断开,队列自动删除。所以实际上这两个参数对exclusive队列没有意义。

3. 将新节点加入已存在的镜像队列时,默认情况下ha-sync-mode=manual,镜像队列中的消息不会主动同步到新节点,除非显式调用同步命令。当 调用同步命令(via rabbitmqctl or web-based ui)后,队列开始阻塞,无法对其进行操作,直到同步完毕。当ha-sync-mode=automatic时,新加入节点时会默认同步已知的镜像队列。 由于同步过程的限制,所以不建议在生产环境的active队列(有生产消费消息)中操作。

4. 每当一个节点加入或者重新加入(例如从网络分区中恢复回来)镜像队列,之前保存的队列内容会被清空。

5. 镜像队列有主从之分,一个主节点(master),0个或多个从节点(slave)。当master宕掉后,会在slave中选举新的master。选举算法为最早启动的节点。

6. 当所有slave都处在(与master)未同步状态时,并且ha-promote-on-shutdown policy设置为when-syned(默认)时,如果master因为主动的原因停掉,比如是通过rabbitmqctl stop命令停止或者优雅关闭OS,那么slave不会接管master,也就是说此时镜像队列不可用;但是如果master因为被动原因停掉,比如VM 或者OS crash了,那么slave会接管master。这个配置项隐含的价值取向是优先保证消息可靠不丢失,放弃可用性。如果ha-promote-on- shutdown policy设置为alway,那么不论master因为何种原因停止,slave都会接管master,优先保证可用性。

7. 镜像队列中最后一个停止的节点会是master,启动顺序必须是master先起,如果slave先起,它会有30秒的等待时间,等待master启动, 然后加入cluster。当所有节点因故(断电等)同时离线时,每个节点都认为自己不是最后一个停止的节点。要恢复镜像队列,可以尝试在30秒之内同时启 动所有节点。

8. 对于镜像队列,客户端basic.publish操作会同步到所有节点;而其他操作则是通过master中转,再由master将操作作用于salve。 比如一个basic.get操作,假如客户端与slave建立了TCP连接,首先是slave将basic.get请求发送至master,由 master备好数据,返回至slave,投递给消费者。

9. 由8可知,当slave宕掉时,除了与slave相连的客户端连接全部断开之外,没有其他影响。当master宕掉时,会有以下连锁反应:1)与 master相连的客户端连接全部断开。2)选举最老的slave为master。若此时所有slave处于未同步状态,则未同步部分消息丢失。3)新的 master节点requeue所有unack消息,因为这个新节点无法区分这些unack消息是否已经到达客户端,亦或是ack消息丢失在到老 master的通路上,亦或是丢在老master组播ack消息到所有slave的通路上。所以处于消息可靠性的考虑,requeue所有unack的消 息。此时客户端可能受到重复消息。4)如果客户端连着slave,并且basic.consume消息时指定了x-cancel-on-ha- failover参数,那么客户端会收到一个Consumer Cancellation Notification通知,Java SDK中会回调Consumer接口的handleCancel()方法,故需覆盖此方法。如果不指定x-cancel-on-ha-failover参 数,那么消费者就无法感知master宕机,会一直等待下去。

上面列出的注意事项整理自官方的HA文档

下面的镜像队列恢复才是本文重点:

* 前提:两个节点(A和B)组成一个镜像队列。

* 场景1:A先停,B后停。

该场景下B是master,只要先启动B,再启动A即可。或者先启动A,再在30秒之内启动B即可恢复镜像队列。

* 场景2: A, B同时停。

该场景可能是由掉电等原因造成,只需在30秒之内连续启动A和B即可恢复镜像队列。

* 场景3:A先停,B后停,且A无法恢复。

该场景是场景1的加强版,因为B是master,所以等B起来后,在B节点上调用rabbitmqctl forget_cluster_node A,解除与A的cluster关系,再将新的slave节点加入B即可重新恢复镜像队列。

* 场景4:A先停,B后停,且B无法恢复。

该场景是场景3的加强版,比较难处理,早在3.1.x时代之前貌似都没什么好的解决方法,可能是我不知道,但是现在已经有解决方法了,在3.4.2 版本亲测有效。因为B是master,所以直接启动A是不行的,当A无法启动时,也就没办法在A节点上调用rabbitmqctl forget_cluster_node B了。新版本中,forget_cluster_node支 持–offline参数,offline参数允许rabbitmqctl在离线节点上执行forget_cluster_node命令,迫使 RabbitMQ在未启动的slave节点中选择一个作为master。当在A节点执行rabbitmqctl forget_cluster_node –offline B时,RabbitMQ会mock一个节点代表A,执行forget_cluster_node命令将B剔出cluster,然后A就能正常启动了。最后 将新的slave节点加入A即可重新恢复镜像队列。

* 场景5: A先停,B后停,且A、B均无法恢复,但是能得到A或B的磁盘文件。

该场景是场景4的加强版,更加难处理。将A或B的数据库文件(默认在$RABBIT_HOME/var/lib目录中)拷贝至新节点C的目录下,再 将C的hostname改成A或B的hostname。如果拷过来的是A节点磁盘文件,按场景4处理方式;如果拷过来的是B节点磁盘文件,按场景3处理方 式。最后将新的slave节点加入C即可重新恢复镜像队列。

* 场景6:A先停,B后停,且A、B均无法恢复,且无法得到A或B的磁盘文件。

洗洗睡吧,该场景下已无法恢复A、B队列中的内容了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108648.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 执行力与领导力

    执行力与领导力

  • bigdecimal截取2位小数_bigdecimal保留整数两位

    bigdecimal截取2位小数_bigdecimal保留整数两位//保留两位小数并展示千分位符DecimalFormatdf1=newDecimalFormat(“##,##0.00”);System.out.println(df1.format(0.2));//0.20System.out.println(df1.format(0.235));//0.24System.out.println(df1.format(0.2351));//0.24Sy…

  • java字符串分割split没内容_python字符串分割

    java字符串分割split没内容_python字符串分割Java中分割字符串的函数是split。  publicString[]split(Stringregex,intlimit),用Stringregex来分割字符串,返回值是字符串数组Stringword=”小王,小魏,小明,小红”;String[]words=word.split(“,”);//注意这里要用字符串数组接收System.out.println(words

  • 最有效的最新防360拦截方法大全![通俗易懂]

    最有效的最新防360拦截方法大全![通俗易懂]首先声明,现在对于360拦截,没有任何一种方法是绝对有效的。因为存在举报,同一网站举报次数达到5次以上就会有360公司的员工接入人工审核,人工接入的话,再好的技术都是百搭,所以我这里的技术可以说绝对拦得住“机器审核”,具体“拦截时间未知”(因为不知道您的竞争对手什么时候会给您搞点小动作)我总结的方法一共有5种,都做过测试,分析出优缺点。具体如下:方法一:用框架调用主页,也就

    2022年10月23日
  • java启动器_JAVA基础:Java 启动器如何查找类

    java启动器_JAVA基础:Java 启动器如何查找类Java启动器java将初始化Java虚拟机。虚拟机随即按以下顺序搜索和加载类:自举类-构成Java平台的类,包括rt.jar和i18n.jar中的类。扩展类-使用Java扩展机制的类。它们被捆绑为.jar文件,位于扩展目录中。用户类-开发人员和第三方定义的类,不使用扩展机制。在命令行上使用-classpath选项(常用方法)或使用CLASSPATH…

  • 用Python做个微信自动回复机器人

    用Python做个微信自动回复机器人微信已经成为我们生活不可或缺的一部分,每天有380亿条消息从微信上发出,其中6亿条是语音消息,有350万个活跃的公众账号,并存在着8亿活跃粉丝。微信是一个庞大的生态群体。今天我们来玩转一下微信,微信有关的第三方框架很多,比如wxpy,wxBot等。今天要使用的是其中著名的itchatPython模块来做两件有趣的事情。 一个自动回复的机器人微信自上线以来,一直没有自动回复的功能…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号