为何选择 Elasticsearch?
在传统数据库中,商品模糊查询(尤其是前置模糊匹配)会放弃索引,导致全表扫描。在百万级数据规模下,这种查询方式效率极低。而 Elasticsearch(以下简称 ES)通过构建全文索引,将商品名、描述、价格、ID 等高频查询字段纳入索引库,可显著提升查询速度,完美解决这一痛点,因此被广泛应用于各类数据检索场景。
Elasticsearch 集群构成
1. 节点类型定义
ES 集群由多个节点(Node)组成,节点类型通过 conf/elasticsearch.yml 中的两个核心配置项组合确定:
node.master: true/false # 是否为 master 候选节点(可参与选举)
node.data: true/false # 是否为数据节点(存储分片数据,处理读写请求)
基于上述配置,节点分为四种基础类型,另有 Ingest Node(数据预处理节点)等特殊类型暂不赘述:
| 节点类型 | node.master | node.data | 核心功能 |
|---|---|---|---|
| 主节点+数据节点 | true | true | 参与 master 选举,若当选则管理集群状态;同时存储数据、处理读写请求 |
| 仅主节点候选 | true | false | 仅参与 master 选举,不存储数据(适用于大规模集群,减轻主节点负载) |
| 仅数据节点 | false | true | 不参与选举,仅负责数据存储和读写操作(集群扩容的核心节点类型) |
| 代理节点(Proxy) | false | false | 接收客户端请求,转发至对应节点,聚合查询结果(类似网关角色) |
2. 集群拓扑示例
一个典型 ES 集群拓扑如下:
-
NodeA:当前主节点(Master)+ 数据节点
-
NodeB:Master 候选节点 + 数据节点
-
NodeC:Master 候选节点
-
NodeD:仅数据节点
-
NodeE:代理节点
-
特性:每个节点会与集群内所有其他节点建立连接,确保通信畅通。
节点发现机制
ES 采用自研的 ZenDiscovery 模块实现节点发现与选主,无需依赖 Zookeeper 等第三方工具。
1. 核心配置
discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3]
该配置指定了节点初始连接的目标地址,官方推荐配置为所有 Master 候选节点。
2. 发现原理
节点通过配置的地址与其他节点建立连接,当所有节点形成连通图时,即可感知整个集群的节点列表,避免出现“孤岛节点”。
Master 选举机制
为避免集群“脑裂”(多个 Master 并存),ES 采用多数派(quorum)认可原则,核心配置如下:
discovery.zen.minimum_master_nodes: 2 # 成为 Master 所需的最小候选节点认可数
1. 选举触发条件
Master 候选节点满足以下条件时,发起选举:
-
自身当前非 Master 状态;
-
通过 ZenDiscovery 的 ping 操作确认,无节点连接到现有 Master;
-
包括自身在内,超过
minimum_master_nodes个候选节点均未连接到 Master。
2. 候选人排序规则
选举时按以下优先级排序,取首位作为目标 Master:
-
集群状态版本号(clusterStateVersion):数值越大优先级越高;
-
节点 ID:版本号相同时,ID 越小优先级越高。
3. 选举流程
-
候选节点发起选举,根据排序规则确定目标 Master(可能是自身或其他节点);
-
若目标为其他节点(如 NodeA 选 NodeB):
-
若 NodeB 已为 Master,NodeB 会将 NodeA 加入集群,发布新集群状态;
-
若 NodeB 正在竞选,NodeA 的请求视为“选票”,NodeA 等待 NodeB 竞选结果;
-
若 NodeB 拒绝竞选,NodeA 开启下一轮选举;
-
-
若目标为自身(如 NodeA 选自己):
-
NodeA 等待其他候选节点的“选票”(join 请求);
-
收集到超过半数选票时,NodeA 确认成为 Master,更新集群状态并发布。
-
4. 脑裂防护
核心逻辑是“多数派认可”:只有获得超过 minimum_master_nodes 个候选节点支持,才能成为 Master。由于不可能有两个节点同时获得多数派支持,因此避免了脑裂。
错误检测与恢复机制
ES 通过两类心跳检测机制(MasterFaultDetection、NodesFaultDetection)实现故障感知,核心是定期 ping 通信。
1. 故障检测场景
-
Master 检测节点故障:
-
Master 发现节点失联后,将其从集群状态中移除,发布新状态;
-
集群自动触发恢复操作(如重新选举主分片、复制数据);
-
-
节点检测 Master 故障:
-
节点发现 Master 失联后,清空未提交的集群状态,发起重新加入(rejoin);
-
若满足选举条件,则触发新 Master 选举。
-
2. 主动 Rejoin 场景
Master 发现自身不再满足多数派条件时,会主动退出 Master 状态并执行 rejoin,避免脑裂:
-
移除失联节点后,剩余候选节点数不足
minimum_master_nodes; -
发布集群状态时,发送阶段(send)未获得多数派确认;
-
检测到集群中存在其他 Master,且自身集群状态版本更低。
集群扩缩容实践
1. 数据节点(DataNode)扩容
-
配置新节点:
node.master: false node.data: true cluster.name: es-cluster # 需与目标集群名称一致 node.name: node_Z discovery.zen.ping.unicast.hosts: ["x.x.x.x", "x.x.x.y", "x.x.x.z"] # 配置集群中 Master 候选节点地址 -
启动节点,集群会自动触发分片均衡(rebalance),或通过 reroute API 手动调整。
2. 数据节点缩容
-
禁止分片分配到待下线节点:
PUT _cluster/settings { "transient": { "cluster.routing.allocation.exclude._ip": "10.0.0.1" # 待下线节点 IP } } -
等待节点上所有分片迁移完成后,安全下线节点。
3. Master 候选节点扩容
-
调整多数派阈值(避免脑裂):
curl -XPUT localhost:9200/_cluster/settings -d '{ "persistent": { "discovery.zen.minimum_master_nodes": 3 # 例如:3 个候选节点扩容至 4 个时,阈值从 2 调整为 3 } }' -
配置新节点为 Master 候选节点(
node.master: true),启动后加入集群。 -
注意:配置文件中的阈值与集群元数据(cluster meta)中的阈值需保持一致,避免集群重启时出现选举异常。
4. Master 候选节点缩容
-
先将目标节点下线;
-
待集群稳定后,降低
minimum_master_nodes阈值(与扩容流程相反)。 -
警告:Master 节点及相关配置变更风险极高,错误操作可能导致脑裂、数据损坏或丢失。
基于 Zookeeper 的替代实现方案
1. Zookeeper 核心能力
Zookeeper 是分布式系统的协调工具,可解决节点管理、配置同步、主从选举等问题,核心特性包括:
-
数据存储:以目录树结构管理 znode,每个 znode 包含状态(stat)、数据(data)、子节点(children);
-
临时节点:session 结束后自动删除,适用于选举和故障检测;
-
Watch 机制:监听 znode 的增减、更新事件,实现状态同步。
2. Zookeeper 实现 ES 核心功能
-
节点发现:节点启动后在 Zookeeper 特定目录注册临时 znode,Master 监听该目录的子节点变化,自动纳入新节点;
-
Master 选举:候选节点竞争注册“master”临时 znode,注册成功者成为 Master,失败者监听该 znode 变化;
-
错误检测:节点或 Master 故障时,对应的临时 znode 自动删除,集群通过 Watch 机制感知并触发重新选举;
-
集群扩缩容:无需手动调整
minimum_master_nodes,操作更简洁。
3. Zookeeper 方案优劣
| 优势 | 劣势 |
|---|---|
| 简化 ES 分布式一致性逻辑,正确性有保障 | 增加集群依赖,部署和运维复杂度提升 |
| 避免 ZenDiscovery 的潜在 Bug | 额外占用服务器资源 |
| 扩缩容更便捷 | 学习成本增加(需掌握 Zookeeper 基础) |
ES 选举算法与 Raft 算法对比
Raft 是主流分布式一致性算法,与 ES 自研选举算法的核心差异如下:
1. 相同点
-
多数派原则:均需获得超过半数节点支持才能当选主节点;
-
数据一致性保障:当选主节点均拥有最新已提交数据(ES 靠 clusterStateVersion,Raft 靠日志复制)。
2. 不同点
| 对比维度 | ES 选举算法 | Raft 算法 |
|---|---|---|
| 正确性 | 未经过严格数学论证,依赖实践 Bug 修复 | 经过严格论证,正确性有理论保障 |
| 选举周期 | 无 term 概念,无法保证单轮选举每个节点仅投一票 | 引入 term 机制,每轮选举 term 递增,每个节点仅投一票 |
| 选举倾向性 | 版本相同时,NodeID 越小优先级越高 | 只要节点拥有最新数据,即有机会当选 |
3. 总结
Raft 算法在正确性和规范性上更优,ES 选举算法经多次迭代后逐渐向 Raft 靠拢。由于 ES 开发初期 Raft 尚未普及,未来可能逐步演进为 Raft 实现。


