跳转至主要内容
版本:4.1

集群和网络分区

简介

本指南涵盖集群的一个特定方面:节点之间的网络故障、其影响和恢复选项。有关集群的总体概述,请参阅集群对等发现和集群形成指南。

集群可用于实现不同的目标:通过复制提高数据安全性,提高客户端操作的可用性,提高整体吞吐量等等。不同的配置对于不同的目的来说是最佳的。

集群成员之间的网络连接故障会对数据一致性和客户端操作的可用性(如 CAP 定理中所示)产生影响。由于不同的应用程序对一致性的要求不同,并且可以容忍不同程度的不可用性,因此可以使用不同的分区处理策略

检测网络分区

如果节点在一段时间(默认 60 秒)内无法联系到其对等节点,则节点会确定其对等节点已关闭。如果两个节点恢复联系,并且都认为对方已关闭,则节点将确定发生了分区。这将以如下形式写入 RabbitMQ 日志中

2020-05-18 06:55:37.324 [error] <0.341.0> Mnesia(rabbit@warp10): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, rabbit@hostname2}

可以通过服务器日志HTTP API(用于监控)和CLI 命令识别分区存在

rabbitmq-diagnostics cluster_status

rabbitmq-diagnostics cluster_status 通常会显示一个空的分区列表

rabbitmq-diagnostics cluster_status
# => Cluster status of node rabbit@warp10 ...
# => Basics
# =>
# => Cluster name: local.1
# =>
# => ...edited out for brevity...
# =>
# => Network Partitions
# =>
# => (none)
# =>
# => ...edited out for brevity...

但是,如果发生了网络分区,则有关分区的信息将出现在那里

rabbitmqctl cluster_status
# => Cluster status of node rabbit@warp10 ...
# => Basics
# =>
# => Cluster name: local.1
# =>
# => ...edited out for brevity...
# =>
# => Network Partitions
# =>
# => Node flopsy@warp10 cannot communicate with hare@warp10
# => Node rabbit@warp10 cannot communicate with hare@warp10

HTTP API 将在 GET /api/nodes 端点中返回每个节点下 partitions 中的分区信息。

如果发生分区,管理 UI 将在概览页面上显示警告。

网络分区期间的行为

当网络分区存在时,集群的两侧(或更多侧!)可以独立演变,两侧都认为另一侧已崩溃。这种情况被称为脑裂。队列、绑定、交换机可以单独创建或删除。

Quorum 队列将在多数方选举新的领导者。少数方的 Quorum 队列副本将不再取得进展(即接受新消息、传递给消费者等),所有这些工作将由新的领导者完成。

除非配置了诸如 pause_minority 之类的分区处理策略,否则即使在网络连接恢复后,分裂仍将继续。

由挂起和恢复引起的分区

当我们提到“网络”分区时,实际上分区是指集群的不同节点之间的通信中断,而没有任何节点发生故障的任何情况。除了网络故障外,对正在运行的集群节点使用挂起和恢复整个操作系统也可能导致分区 - 因为挂起的节点不会认为自身发生故障,甚至停止,但集群中的其他节点会认为它已经发生故障。

虽然您可以通过在笔记本电脑上运行集群节点并合上盖子来挂起它,但发生这种情况的最常见原因是虚拟机被虚拟机监控程序挂起。

虽然在虚拟化环境或容器中运行 RabbitMQ 集群是可以的,但请确保虚拟机在运行时不会被挂起

请注意,某些虚拟化功能(例如将 VM 从一台主机迁移到另一台主机)通常会涉及 VM 被挂起。

由挂起和恢复引起的分区往往是不对称的 - 挂起的节点不一定将其他节点视为已关闭,但会被集群的其余部分视为已关闭。这对于 pause_minority 模式具有特殊的含义。

从脑裂中恢复

要从脑裂中恢复,首先选择您最信任的一个分区。此分区将成为系统状态(模式、消息)的权威;在其他分区上发生的任何更改都将丢失。

停止其他分区中的所有节点,然后重新启动它们。当它们重新加入集群时,它们将从受信任的分区恢复状态。

最后,您还应该重新启动受信任分区中的所有节点以清除警告。

停止整个集群并重新启动它可能会更简单;如果是这样,请确保您启动的第一个节点来自受信任的分区。

分区处理策略

RabbitMQ 还提供了三种自动处理网络分区的方法:pause-minority 模式、pause-if-all-down 模式和 autoheal 模式。默认行为被称为 ignore 模式。

在 pause-minority 模式下,RabbitMQ 将自动暂停集群节点,这些节点在看到其他节点关闭后,确定自己处于少数(即,少于或等于节点总数的一半)。因此,它从 CAP 定理中选择分区容错而不是可用性。这确保在发生网络分区时,最多只有一个分区中的节点将继续运行。少数节点将在分区开始时立即暂停,并在分区结束时再次启动。此配置可防止脑裂,因此能够自动从网络分区中恢复,而不会出现不一致。

在 pause-if-all-down 模式下,RabbitMQ 将自动暂停无法访问任何列出节点的集群节点。换句话说,列出的所有节点都必须关闭,RabbitMQ 才会暂停集群节点。这与 pause-minority 模式接近,但是,它允许管理员决定首选哪些节点,而不是依赖于上下文。例如,如果集群由机架 A 中的两个节点和机架 B 中的两个节点组成,并且机架之间的链接丢失,则 pause-minority 模式将暂停所有节点。在 pause-if-all-down 模式下,如果管理员列出了机架 A 中的两个节点,则只有机架 B 中的节点会暂停。请注意,列出的节点可能会在分区的两侧之间拆分:在这种情况下,没有节点会暂停。这就是为什么还有一个额外的ignore/autoheal 参数来指示如何从分区中恢复。

在 autoheal 模式下,如果认为发生了分区,RabbitMQ 将自动决定一个获胜分区,并将重新启动不在获胜分区中的所有节点。与 pause_minority 模式不同,它在分区结束时生效,而不是在分区开始时生效。

获胜分区是连接客户端最多的分区(或者,如果这产生平局,则节点最多的分区;如果仍然产生平局,则以未指定的方式选择其中一个分区)。

您可以通过在配置文件中将 rabbit 应用程序的配置参数 cluster_partition_handling 设置为以下值来启用任一模式

  • autoheal
  • pause_minority
  • pause_if_all_down

如果使用 pause_if_all_down 模式,则需要其他参数

  • nodes:应不可用以暂停的节点
  • recover:恢复操作,可以是 ignoreautoheal

使用 pause_if_all_down 的示例配置代码片段

cluster_partition_handling = pause_if_all_down

## Recovery strategy. Can be either 'autoheal' or 'ignore'
cluster_partition_handling.pause_if_all_down.recover = ignore

## Node names to check
cluster_partition_handling.pause_if_all_down.nodes.1 = rabbit@myhost1
cluster_partition_handling.pause_if_all_down.nodes.2 = rabbit@myhost2

选择哪种模式?

重要的是要了解,允许 RabbitMQ 自动处理网络分区会带来权衡。

如简介中所述,要通过通常不可靠的链接连接 RabbitMQ 集群,请首选联合Shovel

话虽如此,以下是一些指南,可帮助操作员确定哪种模式可能或可能不合适

  • ignore:当网络可靠性尽可能高且节点可用性最为重要时使用。例如,所有集群节点可以位于同一机架或等效机架中,通过交换机连接,并且该交换机也是通往外部世界的路由。

  • pause_minority:适用于跨机架或单区域中的可用区进行集群,并且一次丢失大多数节点(区域)的可能性被认为非常低时。此模式牺牲了一些可用性,以换取在丢失的节点返回时自动恢复的能力。

  • autoheal:当您更关心服务连续性而不是跨节点的数据一致性时适用。

关于 Pause-minority 模式的更多信息

暂停节点上的 Erlang VM 将继续运行,但节点将不会侦听任何端口或以其他方式可用。它们将每秒检查一次以查看集群的其余部分是否重新出现,如果重新出现则重新启动。

请注意,即使节点在启动时处于少数,它们也不会在启动时进入暂停状态。预计启动时的任何此类少数情况都是由于集群的其余部分尚未启动。

另请注意,RabbitMQ 将暂停不属于集群严格多数的节点 - 即包含超过一半的节点。因此,在两个节点的集群上启用 pause-minority 模式不是一个好主意,因为在发生任何网络分区或节点故障时,两个节点都将暂停。但是,对于完整性而言,pause_minority 模式比 ignore 模式更安全。对于超过两个节点的集群,特别是如果网络分区最可能的形式是少数节点从网络中掉线,则可用性与 ignore 模式一样好。

请注意,pause_minority 模式对于防御由集群节点挂起引起的分区无能为力。这是因为挂起的节点永远不会看到集群的其余部分消失,因此不会触发自身与集群断开连接。

© . All rights reserved.