你好,我是风一样的树懒,一个工作十多年的后端专家,曾就职京东、阿里等多家互联网头部企业。公众号"吴计可师",已经更新了过百篇高质量的面试相关文章,喜欢的朋友欢迎关注点赞
Elasticsearch Master 选举:代码、原理与流程图解析
Elasticsearch 的 Master 选举是其集群高可用的基石。一个稳定的 Master 节点是集群正常运作的关键,它负责管理集群的元数据(如索引、分片、节点信息等),并确保集群的协调一致。理解 Master 选举机制,尤其是 7.x 版本之后引入的投票配置(Voting Configuration),对于维护和优化 Elasticsearch 集群至关重要。
为什么需要 Master 节点?
想象一个乐队,如果没有一个指挥,大家各吹各的调,那肯定是一团糟。Elasticsearch 集群也是如此。Master 节点就扮演着这个"指挥家"的角色:
- 集群状态管理: 负责维护并发布集群状态(Cluster State),这是集群所有元数据的唯一真实来源,包括节点信息、索引列表、分片分配、模板设置等。
- 节点管理: 追踪集群中所有节点的状态,包括节点的加入和离开。
- 索引和分片管理: 负责索引的创建、删除,以及分片的分配和迁移。
Master 选举的触发场景
Master 选举并非一直都在进行,它只在特定情况下被触发:
- 集群首次启动: 当一个全新的 Elasticsearch 集群第一次启动时,所有 Master-eligible 节点会尝试选举出第一个 Master。
- 当前 Master 节点故障: 现有 Master 节点因为硬件故障、网络问题、JVM 崩溃或被手动停止而下线时,集群会立即启动新的 Master 选举。
- 网络分区(Split Brain)恢复: 当集群因网络问题导致"脑裂"时,各个子集群可能会尝试选举 Master。在网络恢复后,为了合并成一个健康集群,也会触发 Master 选举。
- Master 节点主动降级: 某些情况下(例如,Master 节点发现自己不再拥有投票配置的多数票),它会主动放弃 Master 角色,触发新的选举。
核心概念:投票配置(Voting Configuration)与 Master-eligible 节点
在 7.x 版本中,Elasticsearch 摒弃了容易误配置的 minimum_master_nodes
,转而使用更智能、更健壮的投票配置(Voting Configuration)。
-
Master-eligible 节点: 任何可以被选举为 Master 的节点。在
elasticsearch.yml
中,通过node.roles
配置:yaml# 一个典型的 Master-eligible 节点配置 node.roles: [master, data, ingest] # 既是 Master 候选,也存储数据,处理摄入 # 或者,独立 Master 节点(不存储数据,推荐在大集群中使用) # node.roles: [master]
最佳实践: 为了高可用性,建议集群中至少有 3 个或 5 个 Master-eligible 节点。奇数个节点更有利于形成多数派,避免"脑裂"。
-
投票配置(Voting Configuration): 这是一个动态维护的 Master-eligible 节点集合。只有投票配置中的节点才有权在 Master 选举中投票。Master 节点会负责管理和更新这个集合,例如当新的 Master-eligible 节点加入或现有节点离开时。
Master 选举流程详解
当一个节点启动或发现当前集群没有 Master 时,它会启动一个 Master 选举过程。这个过程大致可以分为以下几个阶段:
详细步骤解析
-
发现阶段(Discovery Phase):
-
目的: 找到集群中的其他节点。
-
配置: 使用
discovery.seed_hosts
参数来指定一些初始的主机地址,这些地址通常是集群中所有 Master-eligible 节点的 IP 或主机名。yaml# elasticsearch.yml 配置示例 discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
每个节点会向
seed_hosts
中的地址发送 ping 请求,尝试发现其他 Master-eligible 节点,并交换各自已知的集群状态版本信息。
-
-
收集候选节点并排序:
- 当一个节点认为自己需要参与 Master 选举时,它会收集所有它能通信到的 Master-eligible 节点列表,作为 Master 候选。
- 然后,它会根据以下两个主要标准对这些候选节点进行排序(优先级从高到低):
clusterStateVersion
优先级: 拥有最高clusterStateVersion
的节点优先级最高。 这非常重要,因为clusterStateVersion
代表了节点所持有的集群元数据的最新程度。选举拥有最新元数据的节点作为 Master,可以最大程度地避免集群状态回滚或丢失最新配置。- 节点 ID 优先级: 如果多个节点的
clusterStateVersion
相同,则节点 ID (Node ID) 字符串排序值最低(字母顺序靠前)的节点优先级更高。 节点 ID 是 Elasticsearch 启动时为每个节点生成的唯一随机字符串。这个规则是为了在所有其他条件都相同的情况下,提供一个确定的、可预测的选举结果,避免无限循环的选举冲突。
-
投票与决策:
- 每个参与选举的节点会向它自己排序出来的"最佳候选节点"发送投票(Vote)。
- 一个节点要想成为 Master,它必须从投票配置中的多数节点 那里获得投票。
- 示例: 如果集群有 3 个 Master-eligible 节点(A, B, C),并且它们都在投票配置中。那么要成为 Master,至少需要 2 票(即 3/2 + 1 = 2.5,向上取整为 2)。
- 如果一个节点收到了足够多的投票,它就会宣布自己成为 Master。
-
发布集群状态(Publishing Cluster State):
- 新当选的 Master 节点会立即向集群中的所有其他节点发布最新的集群状态(Cluster State)。这个状态包含了所有最新的集群配置、索引信息和分片分配。
- 其他节点收到并确认这个新的集群状态后,它们就会承认新的 Master,并更新自己的本地状态,使整个集群达到一致。
防止脑裂(Split Brain):投票配置的威力
"脑裂"是分布式系统中的一个大忌。它发生在网络分区时,一个集群被一分为二,各自选举自己的 Master,导致数据不一致。Elasticsearch 7.x 通过投票配置的多数派原则彻底解决了这个问题。
- 工作原理: 当 Master 节点发现它不再能够联系到投票配置中的多数节点 时,它会主动降级(step down),放弃 Master 角色。
- 示例: 假设你有 3 个 Master-eligible 节点(Node1, Node2, Node3)。初始投票配置包含所有这 3 个节点。
- 场景 1:Node1 是 Master,Node2 宕机。 Node1 仍然能联系到 Node3。在 3 个节点的投票配置中,Node1 和 Node3 仍然组成了 2 个节点的多数派(2 > 3/2=1.5)。Node1 继续保持 Master 身份。
- 场景 2:Node1 是 Master,Node2 和 Node3 之间网络断开。 导致集群被分隔为两个子集群:{Node1, Node2} 和 {Node3}。
- Node1 视角: Node1 发现它无法联系到投票配置中的多数(它只能联系到 Node2,而需要联系到 2 个节点才能形成多数)。因此,Node1 会主动降级。
- Node3 视角: Node3 也发现自己无法联系到投票配置中的多数。
- 结果是,没有一个子集群能够选举出 Master,从而避免了脑裂。当网络恢复时,节点会重新发现彼此,并启动新的 Master 选举。
首次启动集群的特殊配置:cluster.initial_master_nodes
对于全新的 Elasticsearch 集群,你需要在第一次启动时使用 cluster.initial_master_nodes
参数来"引导"集群。这个参数列出了集群首次启动时希望成为 Master 的 Master-eligible 节点的名称。
yaml
# elasticsearch.yml 配置示例 - 仅用于首次启动全新集群
# Node1 的 elasticsearch.yml
cluster.name: my-es-cluster
node.name: node-1
node.roles: [master, data]
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"] # 列出所有 Master-eligible 节点的名称
# Node2 的 elasticsearch.yml
cluster.name: my-es-cluster
node.name: node-2
node.roles: [master, data]
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
# Node3 的 elasticsearch.yml
cluster.name: my-es-cluster
node.name: node-3
node.roles: [master, data]
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
重要提示: cluster.initial_master_nodes
只在集群首次启动时有效。 一旦集群成功形成,这个设置就会被忽略,并且不应该在后续的节点重启或扩容时再次设置,否则可能导致问题。
总结与展望
Elasticsearch 的 Master 选举机制通过智能的投票配置 和多数派原则,有效地解决了分布式系统中的"脑裂"问题,确保了集群的高可用性。理解其背后的原理和配置,对于构建和维护稳定、高性能的 Elasticsearch 集群至关重要。
今天文章就分享到这儿,喜欢的朋友可以关注我的公众号,回复"进群",可进免费技术交流群。博主不定时回复大家的问题。 公众号:吴计可师