Appearance
Elasticsearch架构
要理解Elasticsearch(以下简称ES)的架构设计,核心要抓住两个关键词:分布式(解决大规模数据的水平扩展)和实时性(兼顾搜索与分析的低延迟)。ES的架构是基于Lucene的分布式封装,通过分层设计将单机Lucene的能力扩展到集群,同时解决了高可用、负载均衡、数据一致性等分布式难题。
一、先明确基础:ES与Lucene的关系
Lucene是单机版的倒排索引库,是ES的“底层引擎”——它负责实现搜索的核心逻辑(如分词、倒排索引构建、评分),但本身不支持分布式。
ES则是Lucene的分布式化容器:
- ES的索引(Index)对应多个Lucene索引(通过“分片”拆分);
- ES的**文档(Document)**对应Lucene的“文档”;
- ES通过集群管理、分片调度、副本同步等机制,将Lucene的单机能力升级为分布式服务。
二、ES的核心架构分层
ES的架构可分为节点层、分布式层、核心功能层三个核心层级,下面逐层拆解:
1. 节点层:集群的最小单元
ES集群由多个节点(Node)组成,每个节点是一台运行ES进程的服务器。节点通过角色分工实现集群的功能拆解,常见角色如下:
| 节点角色 | 职责说明 |
|---|---|
| 主节点(Master-Eligible) | 管理集群状态(如节点加入/离开、索引元数据、分片分配);选举主节点(仅1个 active 主节点)。 |
| 数据节点(Data) | 存储数据(分片);处理数据的写入、查询、聚合操作;是集群的“数据载体”。 |
| 协调节点(Coordinating) | 接收客户端请求,转发到对应数据节点;合并分片结果返回给客户端(默认所有节点都有此功能)。 |
| Ingest节点 | 数据写入前的预处理(如字段转换、添加时间戳、过滤脏数据);类似“数据管道”。 |
| 机器学习节点(ML) | 运行 anomaly detection、数据预测等机器学习任务(需商业版支持)。 |
注意:一个节点可同时承担多个角色(如主节点+数据节点),但生产环境通常会分离主节点与数据节点(避免主节点被数据操作拖垮)。
2. 分布式层:解决“大规模”问题的核心
ES的分布式能力通过**分片(Shard)和副本(Replica)**实现,这是理解ES架构的关键。
(1)分片:水平扩展的基石
ES的索引(Index)会被拆分为多个分片(Shard),每个分片是独立的Lucene索引(即每个分片可单独处理搜索请求)。
- 主分片(Primary Shard):数据写入的“主入口”,每个索引的主分片数在创建时指定(不可修改,默认5个);
- 副本分片(Replica Shard):主分片的拷贝,用于高可用(主分片故障时自动升级为新主分片)和读扩展(分担查询压力);副本数可动态调整(默认1个)。
示例:若创建索引时设置number_of_shards=5、number_of_replicas=1,则该索引共有5(主)+5(副本)=10个分片,分布在集群的不同节点上。
(2)分片路由:数据怎么找到“家”?
当写入文档时,ES通过路由算法确定文档归属的主分片:
java
// 默认路由算法:文档ID的哈希值 % 主分片数
shard_id = hash(document_id) % number_of_primary_shards- 路由结果决定了文档会被发送到哪个主分片所在的节点;
- 若自定义路由键(如
user_id),可保证同一用户的文档落在同一分片(方便聚合查询)。
(3)分片分配与高可用
主节点负责分片的分配与迁移,遵循以下规则:
- 主分片不能与自身副本在同一节点(避免单点故障);
- 副本分片尽量分布在不同机架/可用区(容灾);
- 当节点加入/离开集群时,主节点会自动重新分配分片(如节点宕机,将其上面的主分片迁移到其他节点,并提升副本为主分片)。
3. 核心功能层:搜索与分析的实现
ES的核心功能(写入、查询、聚合)基于Lucene,但通过分布式机制扩展了能力,下面重点讲数据写入流程和查询流程:
(1)数据写入流程(保证可靠性与实时性)
ES的写入流程是**“先写日志,再写内存,最后持久化”,核心是平衡实时性与数据安全性**:
- 客户端请求:客户端将文档发送到协调节点;
- 路由分片:协调节点通过路由算法找到主分片所在的节点,转发请求;
- 主分片写入:
- 先写Translog(事务日志,append-only):记录所有写入操作,用于 crash 恢复(若节点宕机,可通过Translog恢复未持久化的数据);
- 再写内存缓冲区(In-Memory Buffer):文档暂时存储在内存中;
- Refresh(实时化):默认每隔1秒,ES将内存缓冲区的数据写入文件系统缓存(FileSystem Cache),生成不可变的Segment(Lucene的索引文件)。此时文档可被搜索到(这就是ES“实时搜索”的原因);
- 副本同步:主分片将文档同步到所有副本分片(副本执行与主分片相同的写入流程);
- Flush(持久化):默认每隔30分钟(或Translog达到一定大小),ES将文件系统缓存中的Segment刷到磁盘,并清空Translog。此时数据真正持久化。
关键结论:
- Translog保证了“写入不丢数据”;
- Refresh保证了“秒级实时搜索”;
- Flush保证了“数据最终持久化”。
(2)数据查询流程(分布式查询的合并)
ES的查询是**“分散-收集”**模式,核心是利用副本实现读扩展:
- 客户端请求:客户端将查询发送到协调节点;
- 查询规划:协调节点根据路由信息,找到所有相关的分片(主分片或副本分片);
- 并行查询:协调节点向所有目标分片发送查询请求(默认轮询选择副本,均衡负载);
- 结果合并:各分片返回查询结果(如Top N文档),协调节点合并结果(排序、去重)后返回给客户端;
- 聚合计算:若涉及聚合(如统计每个类别的文档数),则先在各分片上做“局部聚合”,再在协调节点做“全局聚合”。
三、集群管理:保证分布式的稳定性
ES的集群管理由主节点和Zen Discovery(发现模块)共同实现,核心解决两个问题:节点发现和主节点选举。
1. 节点发现(Zen Discovery)
节点通过**种子节点(Seed Nodes)**加入集群:
- 节点启动时,会连接配置好的种子节点;
- 种子节点返回当前集群的状态(如主节点地址、已有节点列表);
- 新节点向主节点发送“加入请求”,主节点将其加入集群,并广播集群状态给所有节点。
2. 主节点选举(避免脑裂)
当原主节点宕机时,master-eligible节点会选举新的主节点,遵循**Quorum(仲裁)**规则:
- 需获得超过半数的master-eligible节点支持才能当选主节点;
- 例如:若有3个master-eligible节点,需至少2个支持(
(3/2)+1=2); - 脑裂预防:若集群分裂为两个部分,只有节点数超过半数的部分能选出主节点,另一部分会进入“等待状态”,避免出现两个主节点(脑裂)。
四、ES架构的核心优势
总结ES架构设计的亮点:
- 水平扩展:通过分片将数据分散到多个节点,支持PB级数据存储;
- 高可用:副本机制保证单节点故障不影响服务,主节点选举保证集群稳定性;
- 实时性:Refresh机制实现秒级搜索,满足日志、监控等实时场景需求;
- 多功能:集成搜索、聚合、分析、地理查询等能力,支持从文本搜索到BI分析的全场景;
- 易用性:RESTful API + JSON格式,支持多语言客户端(Java、Python、Go等)。
五、常见问题与设计细节
- 为什么主分片数不可修改?:因为路由算法依赖主分片数,修改会导致所有文档的路由结果失效(需重新分配所有数据,成本极高);
- 副本数为什么能动态调整?:副本是主分片的拷贝,增加副本数只需同步数据,不影响路由;
- Lucene的Segment为什么是不可变的?:不可变Segment保证了查询的高性能(无需加锁),更新/删除操作通过“标记旧文档为删除”+“写入新Segment”实现,合并Segment时清理删除的数据。
总结
ES的架构设计本质是**“用分布式机制封装Lucene”**:通过分片解决水平扩展,通过副本解决高可用,通过Translog/Refresh解决实时性与可靠性的平衡,通过主节点与Zen Discovery解决集群管理。理解这些核心点,就能掌握ES的“设计灵魂”——让大规模数据的实时搜索与分析变得简单。
