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 分布式搜索流程

一个搜索请求在集群里是怎么跑的?我画个流程图给你看:

  1. 客户端发送搜索请求到任意节点(Coordinating节点)
  2. Coordinating节点解析请求,确定要搜索哪些分片
  3. Coordinating节点把请求分发到所有相关分片(主分片或副本分片都可以)
  4. 每个分片独立执行搜索,返回结果给Coordinating节点
  5. 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的索引管理,包括索引模板、别名、滚动索引这些实战技巧。嗯,到时候我会分享一些我在日志场景下的踩坑经验,敬请期待。