2. ES集群架构:节点类型与分布式原理
好,咱们今天聊聊ES集群的骨架——节点类型和分布式原理。说实话,很多初学者把ES当成一个单机数据库来用,结果一上生产就崩。我见过太多案例了,集群搭起来跑得挺欢,一遇到流量高峰就各种超时、脑裂。说白了,就是没搞懂这些节点各自是干嘛的。
2.1 节点类型:各司其职
ES集群里的节点,不是所有节点都干一样的活。我个人习惯把它们分成四类:Master、Data、Ingest、Coordinating。嗯,这里要注意,一个物理节点可以身兼多职,但生产环境我强烈建议分开部署。
2.1.1 Master节点
Master节点是集群的“大脑”。它负责管理集群的元数据、创建删除索引、分配分片、维护集群状态。你想想看,如果大脑出问题了,整个集群是不是就瘫痪了?
关键配置:
node.master: true—— 标记为候选主节点node.data: false—— 不存储数据node.ingest: false—— 不处理数据预处理
避坑指南: 我曾经遇到过一个集群,只配了1个Master节点。结果这个节点挂了,整个集群直接变成“脑死亡”。后来我学乖了,至少配3个候选主节点,奇数个,防止脑裂。
2.1.2 Data节点
Data节点是集群的“肌肉”。它负责存储数据、执行搜索和聚合操作。说白了,你的数据都躺在这类节点上。
配置示例:
# elasticsearch.yml
node.master: false
node.data: true
node.ingest: false
Data节点对磁盘IO和内存要求很高。我在项目中遇到过,Data节点磁盘满了,导致整个集群进入只读模式。嗯,那场面,运维同学直接崩溃。
2.1.3 Ingest节点
Ingest节点是“数据管道工”。它负责在数据写入前进行预处理,比如字段类型转换、数据清洗、添加时间戳等。
典型场景:
- 日志数据清洗:去掉无用的字段
- 字段类型转换:把字符串转成数字
- 添加地理信息:根据IP解析地理位置
我的经验: 如果数据预处理逻辑很复杂,建议单独部署Ingest节点。否则,Data节点既要存数据又要做预处理,性能会大打折扣。
2.1.4 Coordinating节点
Coordinating节点是“交通警察”。它负责接收客户端请求,把请求分发到合适的Data节点,然后汇总结果返回给客户端。
配置示例:
# elasticsearch.yml
node.master: false
node.data: false
node.ingest: false
你想想看,如果没有Coordinating节点,客户端直接连Data节点,那Data节点既要处理搜索又要响应客户端,压力山大。我建议在集群前端挂几个Coordinating节点,专门做请求路由。
2.2 集群健康状态
ES集群的健康状态,说白了就是看你的数据是否安全。有三种颜色:
| 状态 | 含义 | 影响 |
|---|---|---|
| 绿色 | 所有主分片和副本分片都正常 | 集群完全可用 |
| 黄色 | 所有主分片正常,但部分副本分片缺失 | 数据可读写,但容灾能力下降 |
| 红色 | 部分主分片缺失 | 数据丢失,部分索引不可用 |
注意: 黄色状态不等于“没问题”。我曾经遇到过,集群一直黄色,运维觉得无所谓。结果一个节点挂了,直接变红,数据丢了。所以,黄色状态也要及时处理。
查看集群健康状态:
GET /_cluster/health
# 返回示例
{
"cluster_name": "my_cluster",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 5,
"number_of_data_nodes": 3,
"active_primary_shards": 10,
"active_shards": 18,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 2
}
看到unassigned_shards: 2了吗?这就是黄色状态的原因——有2个副本分片没分配出去。为什么会这样?可能是节点数不够,也可能是磁盘空间不足。
2.3 分布式原理
ES的分布式原理,说白了就是“分而治之”。它把数据切成小块(分片),分散到不同节点上。你想想看,如果所有数据都在一台机器上,那搜索速度能快吗?
2.3.1 分片与副本
分片(Primary Shard): 数据的最小存储单元。一个索引默认有5个主分片。
副本(Replica Shard): 主分片的拷贝,用于容灾和提升查询性能。
关键点:
- 主分片数量在索引创建时确定,之后不能修改
- 副本数量可以动态调整
- 主分片和副本分片不会放在同一个节点上
我的建议: 主分片数量不要拍脑袋定。我一般按这个公式估算:主分片数 = 数据总量 / 每个分片建议大小(20-40GB)。比如你有1TB数据,每个分片30GB,那大概需要35个分片。
2.3.2 数据路由
当你写入一条数据时,ES怎么知道该放到哪个分片?
shard = hash(_routing) % number_of_primary_shards
默认情况下,_routing是文档的ID。ES对ID做哈希计算,然后对主分片数取模,得到目标分片编号。
嗯,这里要注意:如果你修改了主分片数量,这个公式的结果就变了。所以主分片数一旦确定,就不能改了。
2.3.3 分布式搜索流程
一个搜索请求在集群里是怎么跑的?我画个流程图给你看:
- 客户端发送搜索请求到任意节点(Coordinating节点)
- Coordinating节点解析请求,确定要搜索哪些分片
- Coordinating节点把请求分发到所有相关分片(主分片或副本分片都可以)
- 每个分片独立执行搜索,返回结果给Coordinating节点
- Coordinating节点合并所有分片的结果,排序、分页,返回给客户端
避坑指南: 我曾经遇到过,搜索请求特别慢,一查发现所有请求都打到了同一个Data节点上。原因是客户端只连了一个节点,而这个节点既是Coordinating又是Data。后来我加了专门的Coordinating节点,并做了负载均衡,问题就解决了。
2.3.4 脑裂问题
脑裂是分布式系统的经典问题。简单说,就是集群里的节点互相联系不上,各自以为自己是老大,导致数据不一致。
为什么会发生?
- 网络抖动:节点之间网络不稳定
- GC停顿:JVM垃圾回收导致节点暂时无响应
- 节点负载过高:CPU、内存打满,心跳超时
如何预防?
- 设置
discovery.zen.minimum_master_nodes为(候选主节点数/2) + 1 - 使用专用网络:集群内部通信走独立网卡
- 合理配置JVM堆内存:不要超过32GB
血的教训: 我曾经在一个7节点的集群上,只配了2个候选主节点,minimum_master_nodes设为1。结果网络抖动了一下,两个Master节点互相不认,各自选自己为主,集群直接分裂成两个。数据写入混乱,最后只能从快照恢复。从那以后,我再也不敢偷懒了。
2.4 总结
好了,这一章的内容就这些。咱们回顾一下:
- 节点类型:Master管元数据,Data管数据,Ingest管预处理,Coordinating管路由
- 集群健康:绿色正常,黄色有风险,红色数据丢失
- 分布式原理:分片存储、哈希路由、分布式搜索、防脑裂
下一章,咱们聊聊ES的索引管理,包括索引模板、别名、滚动索引这些实战技巧。嗯,到时候我会分享一些我在日志场景下的踩坑经验,敬请期待。