RabbitMQ(六)镜像队列

一、镜像队列
默认情况下,RabbitMQ集群中的队列只会存储在某一个节点上,就是队列声明的那个节点上。当访问集群中的其他节点时,会把请求转发给这个节点来进行处理。当这个节点故障时,集群中的这个队列就表现为不可用。队列可以在多个节点中复制镜像以保障可用性,称之为镜像队列。
 
每一个镜像队列由一个master和若干个slave组成。队列的master通常存储在集群的主节点上,没个队列有自己的主节点,镜像队列的所有操作都会首先在mastEr上执行然后广播给其他镜像。包括消息入队,推送给消费者、和消费确认等。
 
生产者发送的消息会在所有的镜像中存储一份副本,消费者不论连接哪个节点最终都会在master上操作,一旦master确认消费(ack)以后,镜像队列会丢弃这条消息。因此镜像队列虽然增加了可用性(存在多个可用副本),但是多个节点间并没有分摊负载,因为所有节点都会处理全量的消息。
 
如果镜像队列的master宕机了,最老的镜像将会晋升为 新的master。未同步的镜像也可以晋升为master,取决于队列的镜像参数。
 
二、如何配置镜像队列
镜像参数通过policy来配置,一个policy通过正则表达式匹配一个或多个队列。
 
命令行设置:e.g.:
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
控制台设置:
 
参数说明
ha-mode
ha-params
Result
exactly
count
Number of queue replicas (master plus mirrors) in the cluster. A  count  value of 1 means a single replica: just the queue master. If the node running the queue master becomes unavailable,  the behaviour depends on queue durability . A  count  value of 2 means 2 replicas: 1 queue master and 1 queue mirror. In other words: `NumberOfQueueMirrors = NumberOfNodes - 1`. If the node running the queue master becomes unavailable, the queue mirror will be automatically promoted to master according to the  mirror promotion strategy  configured. If there are fewer than  count  nodes in the cluster, the queue is mirrored to all nodes. If there are more than  count  nodes in the cluster, and a node containing a mirror goes down, then a new mirror will be created on another node. Use of `exactly` mode with  `"ha-promote-on-shutdown": "always"`  can be dangerous since queues can migrate across a cluster and become unsynced as it is brought down.
all
(none)
Queue is mirrored across all nodes in the cluster. When a new node is added to the cluster, the queue will be mirrored to that node. This setting is very conservative. Mirroring to a quorum (N/2 + 1) of cluster nodes is  recommended instead . Mirroring to all nodes will put additional strain on all cluster nodes, including network I/O, disk I/O and disk space usage.
nodes
node names
Queue is mirrored to the nodes listed in  node names . Node names are the Erlang node names as they appear in  rabbitmqctl cluster_status ; they usually have the form "rabbit@hostname". If any of those node names are not a part of the cluster, this does not constitute an error. If none of the nodes in the list are online at the time when the queue is declared then the queue will be created on the node that the declaring client is connected to.
三、多少个镜像是最优的
在所有的节点上设置镜像是最保守的策略,可用性最高,但是会给集群中的所有节点带来额外的压力,包括网络IO、磁盘IO和硬盘空间占用。大多数场景下都没有必要在每个节点上都存储一份镜像。
一般来说推荐设置过半节点的镜像,例如3节点集群设置2个镜像,5节点集群设置3个镜像。
一些瞬变的数据或者时间敏感的数据,比如股票净值数据,最好设置少量的镜像甚至不要使用镜像。
 
四、怎么检查队列是否是镜像状态
镜像队列会在后台管理页面显示策略名称和额外的副本数量,例如下面这个队列存在两个副本,即一主一从
 
队列详情
 
如果仅有的一个镜像节点宕机了
 
当添加了一个镜像队列的时候,会打印如下日志
2018-03-01 07:26:33.121 [info] <0.1360.0> Mirrored queue 'two.replicas' in vhost '/': Adding mirror on node hare@warp10: <37324.1148.0>
 
5.队列master定位节点
rabbitmq中的每个队列有一个primary副本,那个副本所在的节点称之为队列master。所有队列的操作都要首选通过master执行然后传播给其他镜像,为了保证消息的FIFO顺序。
队列master可以使用几种不同的策略分布在集群的节点上, 三种声明策略的方式如下:
  1. 使用x-queue-master-locator队列声明参数
  2. 设置queue-master-locator策略key
  3. 在配置文件中定义queue_master_locator
可选择的策略类型:
  • min-masters 选择承载了队列master数量最少的节点
  • client-local 选择客户端声明队列时连接上的那个节点
  • random 随机选择一个节点
 
6.节点策略和迁移master
如果新的策略里面没有指定原来的master所在的节点,设置和修改队列策略可能导致存在的队列master下线。为了保证消息不丢失,rabbitmq会保留现有的master直到至少有一个镜像已经同步,即使同步需要很长时间。一旦同步成功,原master就会下线,随着原来的队列master下线,消费者将会从原来的master丢失连接并且重连。
例如:原来队列在【A,B】节点,A是master,B是mirror。如果我们这个时候设置了新的policy定位在【C,D】节点,设置完成以后,队列将会存在【A,C, D】节点上,等到C或D节点上的镜像队列同步完成,A上面的队列将会下线。
 
7.排他队列的镜像
当声明排他队列的连接关闭的时候,排他队列将会被删除,所以对一个排他队列做镜像或者持久化是没有意义的。因为一旦承载他的节点宕机了,声明他的连接就会被关闭,随之队列将会被删除。
所以排他队列永远不会配置镜像副本或者持久化。
 
8.集群中的非镜像队列
非镜像队列如果队列的master可用的时候(队列存储的那个节点),客户端可以连接任意一个节点对当前队列进行操作,包括声明、绑定、消费管理和消息路由,对当前队列的操作将会被集群路由到对应master节点上进行执行。一旦master节点不可用,
如果队列是持久化的队列,队列将会保持不可用状态直到节点恢复。所有对队列的操作将会失败
如果队列没有持久化,队列将会被删除。
如果想要保证在任何时候队列依然可用,可以把镜像队列配置为  promoted to master even when not in sync 即使镜像没有同步也可以晋升为master
 
9.配置镜像队列的几种方式
例如:想要声明一个名称为“ha-two”的策略,策略内容是匹配队列名以“two.”开头的队列,在集群中任意2个节点上保持镜像,并且自动同步
9.1命令行方式
     rabbitmqctl set_policy ha-two "^two\." \
'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
 
9.2发送HTTP请求
     PUT /api/policies/%2f/ha-two
{
"pattern":"^two\.",
"definition": {
"ha-mode":"exactly",
"ha-params":2,
"ha-sync-mode":"automatic"
}
}
 
9.3后台管理页面上声明
  • 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.
10.镜像队列主从切换
当队列master不可用
1.运行时间最长的镜像将会晋升为master,因为这个镜像最后可能从master全量同步。如果没有镜像完成了全量同步,那么仅存在于master上的消息将会丢失
2.之前连上镜像节点的所有客户端连接都会突然中断。所有发送给客户端但是还没有ACK的消息将会重新入队。这里面包括客户端已经发出ACK但是在发送给master过程中master宕机的,也包括从master广播给镜像队列过程中丢失的消息。无论是哪种情况,新晋升的master只能重新入队还没有ACK的消息。
3.那些监听了cancel事件的消费者将会被通知队列下线
4.因为第二步过程中消息的重新入队,消费者有可能会重复消费到之前已经消费过的消息
5.随着选择的镜像晋升成为master以后,这时发送给镜像队列的消息就不会丢失了。消息发送给镜像节点的操作将会路由到队列master然后广播给其他镜像,如果master再宕机,一旦新的镜像晋升为master以后,发送给镜像的消息将会重新加入到队列中,重复这个过程。
6.在消息正在发布并且客户端已经接受到确认的时候,如果master或镜像节点下线了,同步还没有完成,客户端发送的消息依然会被确认。从这点上来看,发送给镜像队列和非镜像队列没有区别
 
如果消费者使用自动签收模式,消息可能会丢失,这一点和非镜像队列没有区别。因为broker认为自动签收模式下,消息只要发送到消费者了就认为是确认发送成功了。
 
镜像队列的master如果突然挂了,客户端的连接突然中断,如果消费者是自动签收模式,这个时候正在发送给客户端的消息可能永远也不会被消费者接收到了
 
11.master节点故障消费感知
消费者正在消费镜像队列的消息时,如果发生了故障转移,主从切换,哪条消息(发送中的)被发送到哪个消费者的记录将会丢失,因此所有未确认的消息被会被标记 redelivered并且重新发送。
如果消费者想要感知这一行为,可以设置 x-cancel-on-ha-failover参数为true,然后在故障转移的时候,消费行为将会被取消,将会接收到cancel通知。
 
java代码示例
 
Channel channel = ...;
Consumer consumer = ...;
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-cancel-on-ha-failover", true);
channel.basicConsume("my-queue", false, args, consumer);
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值