####################################################
RabbitMQ High Availability
####################################################
1.高可用queue
默认情况下RabbitMQ
cluster中的queues位于单独的节点(queues被首次声明的节点),而exchanges和bindings存在于cluster中各节点。因而每个节点失效exchanges和bindings并无影响,单弱queues所在的节点失效就会影响该节点上存在的queues。但是。queues可以在多个节点上镜像。每个被镜像的queue包含一个master和一个或者多个slave。若原master失效则最旧的slave被提升为新的master。

publish到queue的message会被复制到各个slave、consumers无论从cluster中哪个节点连接都会连接到master上,对于已经自master上被确认的message各slave会丢弃。所以,queue镜像只是增强了可用性。并没有在各节点间均衡负载。

该方案需要RabbitMQ cluster, 不能再cluster内处理network partitions因而不推荐在WAN中使用,仅用于LAN。

2.配置镜像
通过policy进行,可在任意时刻更改,将non-mirrored queue改为mirrored
queue,或者反之。需注意的是non-mirrored
queue与没有slave的mirrore的queue并不相同,前者无需额外mirroring架构运行的更快。
可用的policy
ha-mode   ha-params   行为
all                              queue被mirror到cluster中所有节点。
                                 cluster中新添加节点,queue也会被mirror到该节点。
exactly   count            queue被mirror到指定数目的节点。
                                 count大于cluster中节点数则queue被mirror到所有节点。
                                 若count小于cluster中节点数,在包含mirror的某节点down后不会在其他节点建新的mirror(为避免cluster中queue migrating)
nodes     node names  queue被mirror到指定名字的节点。
                                 若任一名称在cluster中不存在并不会引发错误。
                                若指定的任何节点在queue声明时都不在线则queue在被连接到的节点创建。

关于nodes类型的policy
设置或更改nodes类型的policy可能引起原master迁移。比如原master没有出现的新的lolicy节点列表中时。RabbitMQ采取的策略是保持原master直到至少一个新的slave已经同步,一旦同步后原master马上自动失效。原consumer连接会断掉,需重连。
如,原queue在节点{A,B},A为master。来一个新的policy{C,D},会有一段时间的状态为{A,C,D},待queue同步后A上的master关闭,新的mirror为{C,D}

特殊queue:Exclusivequeues
exclusive queues不会被镜像(mirror)也不会被持久化(durable),即使被声明为如此。因为一但存放queue的节点down了上边的连接也会断掉,对于exclusive queues相关的queue会被马上删除。

3.镜像配置示例(可通过多种方式)
下面的例子将“ha.”开头的queue mirror到cluster中所有节点
rabbitmqctl   rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}'
HTTP API    PUT /api/policies/%2f/ha-all {"pattern":"^ha\.", "definition":{"ha-mode":"all"}}
Web UI        Navigate to Admin > Policies > Add / update a policy.
                  Enter "ha-all" next to Name, "^ha\." next to Pattern, and "ha-mode" = "all" in the first line next to Policy.
                  Click Add policy.

下面的例子将“two.”开头的queue mirror到cluster中两个节点,且自动同步
rabbitmqctl    rabbitmqctl set_policy ha-two "^two\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
HTTP API    PUT /api/policies/%2f/ha-two {"pattern":"^two\.",
"definition":{"ha-mode":"exactly",
"ha-params":2,"ha-sync-mode":"automatic"}}
Web UI        Navigate to Admin > Policies > Add / update a policy.
                   Enter "ha-two" next to Name and "^two\." next to Pattern.
                   Enter "ha-mode" = "exactly" in the first line next to
Policy, then "ha-params" = 2 in the second line, then "ha-sync-mode" =
"automatic" in the third, and set the type on the second line to
"Number".
                   Click Add policy.

下面的例子将“nodes.”开通的queue mirror到cluster中特定的node
rabbitmqctl   rabbitmqctl set_policy ha-nodes "^nodes\." '{"ha-mode":"nodes","ha-params":["nodeA", "nodeB"]}'
HTTP API    PUT /api/policies/%2f/ha-nodes {"pattern":"^nodes\.",
"definition":{"ha-mode":"nodes", "ha-params":["nodeA", "nodeB"]}
Web UI        Navigate to Admin > Policies > Add / update a policy.
                   Enter "ha-nodes" next to Name and "^nodes\." next to Pattern.
                   Enter "ha-mode" = "nodes" in the first line next to
Policy, then "ha-params" in the second line, set the second line's type
to "List", and then enter "nodeA" and "nodeB" in the sublist which
appears.
                  Click Add policy.

4.其他注意事项
非同步的slaves
node可在任意时刻加入RabbitMQ
cluster。根据queue的policy,当一个node加入cluster时,queues可能在这个新的node上添加一个slave。此时此刻,新的slave是空的,并不包含被镜像的queue中存在的内容。该slave将接收publish到其queue的新的message。这样一来,一段时间后salve上的queue相当于被镜像的queue的“尾巴”,且随着时间的推移被镜像的queue的“头部”越来越小,而salve上的queue的“尾巴”越来越长,最终salve的内容会与master上的内容完全同步。需要注意的是,这里有个提前提条件,即客户端需从master上的queue中不断消耗既存的message以达到master和salve的同步。

因此,新添加进的slave并不能为该slave被加入前就已存在的queue内容增加额外的冗余或可用性,直至master/slave完全同步。因为执行明确的同步操作会使queue无响应,因此只允许非活跃的queues进行明确的同步操作而活跃的queues进行自然的同步操作是一种好的策略。

配置明确的同步
明确的/显示的同步操作可以以两种方式触发:手动方式和自动方式。若queue被设置为自动同步则新salve一旦被加入同步便开始进行,queue变的无响应直至同步完成。可以通过将policy中的ha-sync-mode指定为automatic来将同步设置为自动的或者将其指定为manual或者不指定将同步设置为手动的。

可通过如下命令确认哪些salve在同步:
rabbitmqctl list_queues name slave_pids synchronised_slave_pids
手动同步queue:
rabbitmqctl sync_queue name
取消queue同步:
rabbitmqctl cancel_sync_queue name
(也可在management plugin中进行)

停止nodes与同步
当停掉运行有被镜像的queue的master
node后,其他node上的slave将被提升为新的master(假定当时存在一个已完全同步的slave)。当继续停掉nodes后会达到没有多余的slave用来镜像queue的境地,queue此时只存在于一个node中,该node此时为master。若该queue被声明为持久化的,则在仅剩的node被停掉并重启后被声明为持久化的message会仍然存在。通常,这个时候再重启其余的nodes,若这些nodes之前是镜像queue的一部分,则会重新加入被镜像的queue。
然而,目前,在重新加入备镜像的queue时,salve没有办法知道自己的queue中的内容是否和master的queu中的内容存在偏差(这在
network
partition时是可能存在的),因此,目前的策略是,当salve重新加入被镜像的queue时,丢掉本地所有的内容,以空的状态开始,就好比cluster中加入了新node一样。

停止只有未同步的salves的master nodes

在关掉master
node时所有可用的salves都还未同步完的情况是可能的。为了避免message丢失,默认情况下,在有意的/可控的关闭master时(有意的停RabbitMQ服务或关闭OS)RabbitMQ不会fail

over到还未同步完成的slave上,相反整个queue将被关闭就好像未同步完成的salve不存在一样。然而,若是无意的/不可控的关闭master
node时(例如RabbitMQ server或者node crash了或者网络掉电了)将触发master fail over到slave
node即使slave还未同步完成。

若希望在所有情形下(即使slave node还未同步完成)master node都能fail over到其他slave node,则可通过将policy中的ha-promote-on-shutdown由when-synced值为always来实现。

所有slaves处于关闭状态时的master丢失
可能发生这样一种情形,在queue的所有slaves均处于关闭状态时queue的master丢失了(可控/不可控的关闭)。正常情况下queue的nodes中最后一个被关闭的会变成master,在这个节点重启时我们仍希望其作为master(因为该node可能接收了其他node未接收到的新message)。然而,当调用rabbitmqctl

forget_cluster_node命令从cluster中移除一个node时RabbitMQ会试图为master在该node上的每个queue找到一个当前被停掉的salve
node并在这个slave node重新启动后将其“提升”为新的master。若有多个node可供选择,则最近被停掉的salve
node将被选中。

这里需要理解为什么在执行forget_cluster_node命令时RabbitMQ只能选择已停止的slave来提升为master。之所以这样是因为就像“
停止nodes与同步”部分将的:任何slave node在重新启动后会清空本地所有的内容,因而只能选择还处于停止状态的salve。因此,当从cluster中移除“丢失的”master时需在slaves重启之前执行forget_cluster_node命令。

镜像队列的实现和语义

对于每个被镜像的queue存在一个master和多个slaves,各自在不同的node。slaves以完全相同的顺序执行发生在master上的操作因此可以维护与master一致的状态。publish操作仅发生在master上然后由master
broadcasts到所有的slaves。因此从被镜像的queue consume message的 client实际上是从master
consume的。

当一个slave fail后需要做的很少:master仍为master,所有的client不会被通知slave的fail,也无需其他额外的操作。注意:slave的失败可能不会被立即探测到,每个连接的流控机制的干预可以延迟message的发送。

当master fail时,其中一个slave必须被提升为master,此时会发生以下情况:
一个slave被提升为新的master。被提升的slave是“最旧”的slave。因为该slave与原master中内容完全同步的几率最大。然而,也有可能所有的salve都未与master完全同步,此时只有master中存在而slaves中不存在的message将丢失。
slave认为所有之前的consumers的连接突然断开了。因此,它重新将已经投递但还未被确认的messages重新排队。这些“未被确认的”message可能包含client已发出确认但确认在到达master前丢失了的情形也包含client已发出确认且确认已到达master但在master广播给slaves时丢失的情形。在上述任意一种情况下,新的master都必须为他认为未收到确认的message重新排队。
之前请求原master的clients被取消。
由于重新排队,从queue重新consume的clients需要知道此时可能接收到之前已经被处理过的message

在选则的salve变成master时,这段时间内发往原被镜像的queue的message不会丢失:发给被镜像的queue的message总是直接发给master和所有的slaves。因此,一旦master失败,messages将继续被发往slaves且一旦某个salve被完全提升为master这些message将被添加到queue中。

同样,clients发送的使用publisher
confirms确认的message仍然会被正确的确认即使是在message被publish和被confirm之间master(或任何的slave)fail了。因此,从publisher的角度看,发message到mirrored
queue与发message到任何其他类型的queue并无差别。

若是从mirrored
queue使用noAck=true消费message,message就有可能丢失。RabbitMQ认为一旦message被发给了noAck=true的consumer即被视为确认过了,若这时client意外的断开了,message将永远不会被收到。在mirrored

queue情况下,在master故障时queue中被发给noAck=True的consumer的message将永远不会被收到,也不会被新的master重新排队。因为正在consuming的client可能连接在存活的node上,
Consumer Cancellation
Notification机制可以用于检测是否发生了上述情况。当然,在实际应用场景中,若关心message的可靠性则建议使用noAck=false的consumer。

Publisher Confirms 和 Transactions
Mirrored queue支持Publisher Confirms 和
Transactions。在该情形下,confirms和transactions动作在queue的所有mirror中传播。如,只有transaction在queue的所有mirror中都应用后才回返回tx.commit-ok
。同样,只有queue的所有mirror都接收到message后才会给publisher以确认。

流量控制
RabbitMQ使用基于credit的算法来限制message的发送速率。Publishers只有在接收到queue的所有mirrors反馈的credit时才允许publish

message。若salves不能反馈credit则会导致publisher阻塞。Publisher会一直被阻塞直至slaves反馈credit或者直至剩余的nodes认为该slave从cluster断开连接。Erlang通过定期发送tick至所有nodes来监测连接的断开。tick的频率可通过net_ticktime参数配置。

Consumer Cancellation
从mirrored queue消费message的clients可能想要知道它们从中消费message的queue是否发生了fail
over。当mirrored queue发生了fail
over后,关于messages已被发送到哪个consumer的信息将丢失,因此所有未确认的messages会被设置redelivered
flag后重新发送。Consumers可能想要知道是否发生了这个过程。Consumer可以通过将x-cancel-on-ha-failover
设置为true来达到此目的。这样一来在failover发生时消费将取消,
consumer cancellation notification会被发出。接下来由consumer决定是否重新

参考:

http://www.rabbitmq.com/ha.html

转载: https://blog.csdn.net/zyz511919766/article/details/41896823

RabbitMQ概念及环境搭建(四)RabbitMQ High Availability的更多相关文章

  1. RabbitMQ概念及环境搭建(三)RabbitMQ cluster

    测试环境:VMS00781 VMS00782 VMS00386 (centos5.8) 1.先在三台机器上分别安装RabbitMQ Server 2.读取其中一个节点的cookie,并复制到其他节点( ...

  2. odoo开发环境搭建(四):python开发工具IDE pycharm配置

    odoo开发环境搭建(四):python开发工具IDE pycharm配置

  3. 从零搭建ES搜索服务(一)基本概念及环境搭建

    一.前言 本系列文章最终目标是为了快速搭建一个简易可用的搜索服务.方案并不一定是最优,但实现难度较低. 二.背景 近期公司在重构老系统,需求是要求知识库支持全文检索. 我们知道普通的数据库 like ...

  4. .Net RabbitMQ系列之环境搭建于RabbitMQ基本介绍

    本系列主要讲解RabbitMQ在.Net环境下的应用,由于Linux环境下,本人Linux功力有限,所以本系列的RabbitMQ跑在Windows环境中.所以的配置之类都在Windows环境中进行. ...

  5. Go语言学习之1 基本概念、环境搭建、第一个Go程序

    一.环境搭建 见我的这篇博客 https://www.cnblogs.com/xuejiale/p/10258244.html 二.golang语言特性1. 垃圾回收    1) 内存自动回收,再也不 ...

  6. Java基础学习之基础概念与环境搭建(1)

    1.Java基础概念 1.1.Java语言的特点 Java语言是简单易学的 Java语言是面向对象(封装.继承和多态) Java语言是平台无关的(一次编译,到处运行) Java语言是可靠的.安全的(异 ...

  7. QGIS 3.14插件开发——Win10系统PyCharm开发环境搭建四步走

    前言:最近实习要求做一个QGIS插件,网上关于QGIS 3.14插件开发环境搭建的文档不多,而且也不算太全面.正好实习的时候写了一个文档,在这里给大家分享一下. 因为是Word转的Markdown,可 ...

  8. 【rabbitmq】rabbitmq集群环境搭建

    安装rabbitmq-server 总共有3台虚拟机,都安装有rabbitmq服务,安装过程可参考: [rabbitmq]Centos7 下安装rabbitmq 创建用户和vhost 说明: 此步骤不 ...

  9. RabbitMQ集群环境搭建-4

    确保成功安装好JDK,erlang,RabbitMQ等,并且RabbitMQ能正常启动,多台电脑之间能互相ping得通. 1. 安装 erlang.rabbitmq 如: 192.168.1.1.19 ...

随机推荐

  1. 独特的deadlock(仅update语句也能造成死锁)

    最近遇到了一个看上去很奇怪,分析起来很有意思的死锁问题.这个死锁看上去难以理解.而分析过程中,又使用了很多分析SQL Server死锁的典型方法.记录下来整个分析过程还是很有意义的. 问题重现步骤: ...

  2. IOS程式语法之block的使用掌握

    在现阶IOBlock 是iOS在4.0之后新增的程式语法,严格来说block的概念并不算是基础程式设计的范围,对初学者来说也不是很容易了解,但是在iOS SDK 4.0之后,block几乎出现在所有新 ...

  3. Android生成带图片的二维码

    一.问题描述 在开发中需要将信息转换为二维码存储并要求带有公司的logo,我们知道Google的Zxing开源项目就很好的帮助我们实现条形码.二维码的生成和解析,但带有logo的官网并没有提供demo ...

  4. Charles Proxy for Mac & Windows (4.1.3)破解激活工具

    1.简介 2017年7月10日更新本博客,Charles已经更新到了4.1.3版本,并对应地给出破解jar包. Charles是一个Mac和Windows平台都可以使用的抓包工具,它的破解激活非常简单 ...

  5. cognos report同比环比以及默认为当前月分析

    现在的需求是按月份分析不同时期的余额数据,.(报表工具:cognos report:建模工具:FM) ------------------------------------------------- ...

  6. 安装--->Tomcat监控工具Probe

    1.Porbe介绍 psi-probe用于对Tomcat进行监控,比tomcat的manager强大很多. 2.下载 probe-2.3.3.zip  或者  probe.war 3.将下载好的war ...

  7. 用Java发送HTML格式邮件测试类(支持中文)

    代码由纯Java写成,支持中文,一目了然,只要将Main函数中的相关信息填写正确就直接用了,便于修改,可以在此类基础上任意扩展成自己的类. 注意做HTML形式的邮件,最好把HTML,CSS都写全,只写 ...

  8. 把系统时间改到以前后,MyEclipse9.1的工程里的JS文件修改完保存但MyEclipse不会将其不会更新。

    一个任务中,由于本周数据还没有产生,只好把系统时间修改到上周,利用下上周的数据. 修改内容主要是增加查询子句的一个字段,因此,包含SQL的DAO,前台显示的Table和前台操作的JS都需要相应修改,它 ...

  9. 使用curl在命令行中下载文件

    http://m.blog.csdn.net/blog/mayadong7349/7019208 使用curl在命令行中下载文件 linux下curl简单应用详解 http://blog.sina.c ...

  10. Struts2(二)action的三种方式

    一.普通java类 package com.pb.web.action; /* * 创建普通的java类 */ public class HelloAction1 { public String ex ...