【ElasticSearch从入门到架构师】第3章:ES 核心基础概念(架构师必备底层认知)

一、集群、节点、分片、副本:核心架构名词解读

在开始之前,先用一个现实类比帮你建立直觉:

把 ElasticSearch 集群想象成一家大型图书馆连锁。集群是整个连锁品牌,节点是每家分馆,分片是分馆里的书架区域,副本是对热门书架区域的备份复印件。

下面这张结构图展示了它们的物理关系:

1.1 集群(Cluster)

集群是多个 ES 节点的集合,它们共享同一个集群名称(​​cluster.name​​),对外表现为一个整体服务。集群有且只有一个 Active Master 节点,负责维护集群元数据状态(索引信息、节点列表、分片路由表等)。

关键特性:

  • 集群名称是节点发现和加入集群的唯一依据,生产环境绝对不能用默认值 elasticsearch
  • 集群健康状态分三级:🟢 Green(全部正常)/ 🟡 Yellow(主分片正常,有副本缺失)/ 🔴 Red(有主分片不可用)
  • 通过 GET /_cluster/health 可实时查询
1.2 节点(Node)

节点就是运行 ES 进程的一台机器(或一个实例)。每个节点可同时承担多种角色:

|-----------------|------------------------|---------------------|
| 节点角色 | 配置项 | 职责描述 |
| Master-eligible | node.roles: master | 参与 Master 选举,管理集群状态 |
| Data | node.roles: data | 存储分片数据,执行查询和索引 |
| Ingest | node.roles: ingest | 数据预处理管道(如分词、格式转换) |
| Coordinating | 默认每个节点都是 | 接收请求、路由到正确分片、汇总结果 |

架构师视角:生产环境一定要角色分离。Master 节点不要承担数据存储,避免因数据节点 GC 卡顿而导致假死引发重新选举,整个集群因此抖动。

1.3 分片(Shard)

分片是 ES 水平扩展的核心机制。一个索引的数据会被切分成若干个主分片(Primary Shard),分散到不同节点上存储。每个分片本质上就是一个完整的 Lucene 实例,具有独立的倒排索引。

分片路由公式(默认):

复制代码
shard_num = hash(document_id) % number_of_primary_shards

架构师警告:主分片数在索引创建时设定,之后不能修改(这是 ES 的历史设计局限,8.x 引入了 ​​_split​​/​​_shrink​​ API 作为补丁)。所以初始规划必须谨慎,一般按「预期数据量 / 单分片最佳容量(20-40GB)」来估算。

1.4 副本(Replica)

副本分片是主分片的完整拷贝,提供两大价值:

  1. 高可用:主分片所在节点宕机,副本立刻晋升为新主分片
  2. 读扩展:搜索请求可以命中副本,分担主分片读压力

副本可以动态调整数量,不影响数据完整性。副本必须分配在与对应主分片不同的节点上(ES 自动保证)。

二、索引、文档、字段:ES 数据模型与 MySQL 表结构对标

理解 ES 数据模型最快的方式是与 MySQL 做类比,但要同时理解它们本质上的区别:

2.1 索引(Index)

ES 中的索引相当于 MySQL 的数据库+表的结合体,命名规范:

  • 全小写,可用 - 分隔,如 user-logs-2024-01
  • 命名要体现业务语义 + 时间维度(便于后续按时间管理生命周期)

一个文档示例:

Crystal 复制代码
PUT /orders/_doc/1001
{
  "order_id": "1001",
  "user_id": "U888",
  "amount": 299.00,
  "status": "paid",
  "created_at": "2024-01-15T10:30:00Z",
  "items": [
    { "sku": "PHONE-X1", "qty": 1 }
  ]
}
2.2 文档(Document)

文档是 ES 中最小的数据单元,以 JSON 格式存储。每个文档包含:

|-------------------------|-------------------------|
| 元字段 | 含义 |
| _index | 所属索引 |
| _id | 文档唯一 ID(可自定义或自动生成 UUID) |
| _source | 原始 JSON 内容 |
| _version | 版本号,用于乐观锁并发控制 |
| _seq_no / _primary_term | 新版乐观锁字段(替代 _version) |

2.3 字段(Field)与 Mapping

Mapping是 ES 的 schema 定义,相当于 MySQL 的 ​​CREATE TABLE​​。核心区别:

  • Dynamic Mapping(默认开启):ES 可以自动推断字段类型,比如字符串 → text + keyword,数字 → long
  • Explicit Mapping:生产环境强烈建议手动定义,防止类型推断错误导致性能问题

常见字段类型对比:

|-------------|------------------------|---------------|
| MySQL 类型 | ES 类型 | 说明 |
| VARCHAR | text | 全文搜索,会分词 |
| VARCHAR | keyword | 精确匹配,不分词,可聚合 |
| INT/BIGINT | integer / long | 数值范围查询 |
| DATETIME | date | 时间范围查询,支持多种格式 |
| BOOLEAN | boolean | 布尔值 |
| TEXT / JSON | text / object / nested | 复杂内容 |

架构师踩坑:​​text​​ 字段无法用于排序和聚合,要做聚合的字段必须用 ​​keyword​​。很多人忽略这点,导致运行时报错 ​​Fielddata is disabled on text fields by default​​。

三、主分片与副本分片的作用、分配规则、容错机制

3.1 分配规则(Allocation Rules)

ES 的分片分配由 Master 节点统一调度,遵循以下核心规则:

规则一:同一分片的主副本不能在同一节点上

Crystal 复制代码
P0 在 Node1 → R0 只能在 Node2 或 Node3

规则二:副本数不能超过「总节点数 - 1」

Crystal 复制代码
3个节点 → 最多支持 2 个副本(1主 + 2副,每台存一份)

规则三:分片分配感知(Shard Allocation Awareness)

生产环境需配置机架感知,防止整个机架断电导致数据丢失:

Crystal 复制代码
# elasticsearch.yml
cluster.routing.allocation.awareness.attributes: rack_id
node.attr.rack_id: rack1  # 每台机器打标签
3.2 容错机制全景

下面这张图演示了节点 1(Master)宕机后,集群的自愈过程:

容错三步骤总结:

Step 1 → 集群状态变 RED:Master 检测到 Node 1 心跳超时(默认 ​​discovery.zen.ping_timeout​​ = 30s),将其标记为失联,相关主分片变为 Unassigned。

Step 2 → 重新选举 Master(如果 Node 1 是 Master):剩余 Master-eligible 节点通过 Zen Discovery(或 8.x 的 raft 协议)投票选出新 Master,耗时通常在 1~30 秒。

Step 3 → 副本晋升 + 补充新副本,状态恢复 GREEN:新 Master 将失去主分片对应的副本提升为主分片,同时在其他可用节点上创建新的副本,直至所有副本就位,集群恢复 Green。

关键数字:整个切换过程对外服务不中断,但可能有短暂的写入拒绝(1 主 0 副的极端配置)。生产环境至少 1 个副本,配合​​index.unassigned.node_left.delayed_timeout​​(默认1分钟)可避免因节点短暂重启导致的不必要数据迁移。

四、倒排索引核心原理(搜索引擎底层核心,必懂重点)

这是 ES 能在毫秒级完成全文搜索的根本原因,也是面试和架构评审中最高频的考点。

4.1 正排索引 vs 倒排索引

用最直白的方式理解两者的差异:

正排索引(MySQL B+ 树):

Crystal 复制代码
文档ID → 文档内容
Doc1 → "ElasticSearch is a search engine"
Doc2 → "search engine based on Lucene"

问题:要搜包含"search"的文档,必须逐行扫描------O(n) 全表扫。

倒排索引(Inverted Index):

Crystal 复制代码
词项(Term)→ 文档ID列表(Posting List)
"elasticsearch" → [Doc1]
"search"        → [Doc1, Doc2]
"engine"        → [Doc1, Doc2]
"lucene"        → [Doc2]

搜索"search"时,直接查词典 → 取回 ​​[Doc1, Doc2]​​,O(1) 词典查找 + 极快集合运算。

下面这张图展示了从原始文档到倒排索引的完整构建过程:

4.2 倒排索引的完整数据结构

一个完整的 Lucene 倒排索引不只是简单的「词 → 文档列表」,它包含:

Crystal 复制代码
词典(Term Dictionary)
  └── "search" → Posting List
        ├── Doc1: freq=2, positions=[3, 8], offsets=[10-16, 40-46]
        ├── Doc2: freq=1, positions=[5],    offsets=[22-28]
        └── Doc3: freq=1, positions=[1],    offsets=[0-6]

关键组成:

|---------------------|-----------------------------------|---------|
| 结构 | 作用 | 存储在哪 |
| Term Dictionary(词典) | 有序词项列表,支持二分查找 | .tim 文件 |
| Term Index(词典索引) | FST(有限状态转换机)前缀树,加速词典查找 | 内存 |
| Posting List(倒排列表) | 文档 ID 列表(压缩存储,Frame of Reference) | .doc 文件 |
| Frequency(词频) | 该词在每个文档中出现的次数,用于相关性评分 | .doc 文件 |
| Position(位置) | 词项在文档中的位置,用于短语查询 | .pos 文件 |
| Norm(归一化因子) | 文档长度对相关性的惩罚因子 | .nvd 文件 |

4.3 分词器(Analyzer)的三个阶段
Crystal 复制代码
原始文本
   ↓
[Character Filters]  --- 字符过滤(如去 HTML 标签)
   ↓
[Tokenizer]          --- 核心切词(如标准分词、IK中文分词)
   ↓
[Token Filters]      --- 词项过滤(小写化、去停词、同义词扩展)
   ↓
标准化 Token 列表 → 写入倒排索引

中文场景必用:内置分析器对中文支持极差(逐字切分),生产必须安装 ​​analysis-ik​​(IK分词器)或 ​​analysis-smartcn​​,并在 Mapping 中指定 ​​"analyzer": "ik_max_word"​​。

五、ES 数据读写的基本流程(入门版简化流程)

5.1 写入流程

写入六步骤详解:

  1. 客户端发请求:向集群任意节点发送 PUT/POST 请求(该节点自动成为本次请求的协调节点)
  2. 路由计算:协调节点计算 shard_num = hash(_id) % primary_shard_count,确定目标主分片
  3. 转发到主分片:协调节点将请求转发到主分片所在节点
  4. 主分片执行写入:更新内存中的 Lucene 索引段,同时写入 Translog(事务日志,用于崩溃恢复)
  5. 同步到副本:主分片并行将操作转发给所有副本,等待 ACK
  6. 响应客户端:所有配置的副本确认后,返回成功响应
5.2 读取(查询)流程
Crystal 复制代码
客户端
  ↓
协调节点(接收请求)
  ↓
广播到所有相关分片(主分片 or 副本分片,轮询负载均衡)
  ↓
各分片本地执行查询,返回 Top N 文档 ID + 分数
  ↓
协调节点合并所有分片结果,二次排序,取全局 Top N
  ↓
根据文档 ID 回填 _source 内容(fetch 阶段)
  ↓
返回最终结果给客户端

深入点:查询分两个阶段------Query Phase(轻量,只传 ID 和分数)和 Fetch Phase(重量,传完整文档)。​​from + size​​ 的深翻页问题根源就在于每个分片都要返回 ​​from + size​​ 条记录给协调节点做归并,大 ​​from​​ 会导致内存和 CPU 暴涨------这是架构师面试必问点。

六、近实时搜索、刷新、持久化基础机制

这是理解 ES"为什么写完还看不到数据"的关键。

6.1 三个核心概念区分

Refresh(刷新)

  • 将内存写缓冲(Index Buffer)中的数据写入一个新的 Lucene Segment(内存,但对搜索可见)
  • 默认每 1 秒一次(index.refresh_interval = 1s
  • 这就是"近实时(NRT)"的含义:写入后最多 1 秒内可被搜索到
  • 调优:批量写入场景可设为 -1(关闭自动刷新),写完后手动 POST /index/_refresh

Flush(冲刷)

  • 将内存中的 Segment 真正写入磁盘(fsync),并更新 commit point
  • 同时清空对应的 Translog
  • 默认每 30 分钟或 Translog 超过 512MB 时触发
  • Flush 之后数据才真正安全持久化,重启后无需从 Translog 回放

Translog(事务日志)

  • 每次写操作都同步追加到 Translog(默认每次请求 fsync,可调为异步)
  • 作用:崩溃恢复。节点重启后,从最后一次 commit point 的检查点开始,重放 Translog 中未 flush 的操作,重建内存 Segment
6.2 关键参数与性能调优

|-------------------------------------|---------|-------------------------------|
| 参数 | 默认值 | 说明 |
| index.refresh_interval | 1s | 改为 -1 可在批量写入时极大提升性能 |
| index.translog.durability | request | 改为 async 可提升写入 TPS,但有微量数据丢失风险 |
| index.translog.sync_interval | 5s | async 模式下的 fsync 间隔 |
| index.translog.flush_threshold_size | 512mb | Translog 大小触发 flush 的阈值 |
| indices.memory.index_buffer_size | 10% 堆 | 写缓冲占 JVM 堆的比例 |

6.3 Segment Merge(段合并)

refresh 每秒产生一个新 Segment,长期积累会导致搜索性能下降(需扫描更多 Segment)。ES 后台持续执行 Merge 操作,将多个小 Segment 合并为一个大 Segment,同时物理删除被标记为删除的文档(ES 的删除是标记删除,Merge 时才真正释放空间)。

优化提示:对于只追加不修改的时序数据(如日志),可以对历史索引执行 ​​POST /index/_forcemerge?max_num_segments=1​​,将每个分片合并为单一 Segment,大幅提升查询性能,同时释放磁盘空间。


本章重点总结

|------------------|---------------------------------|------------------------------------|
| 知识点 | 一句话总结 | 面试/架构要点 |
| 集群 | 多节点统一对外服务 | 集群名不能用默认值,Green/Yellow/Red 三态 |
| 节点角色 | Master/Data/Ingest/Coordinating | 生产环境必须角色分离,Master 不存数据 |
| 分片 | 数据水平切分的基本单元 | 主分片数创建后不可改,规划要按数据量估算 |
| 副本 | 主分片的完整备份 | 可动态调整,必须在不同节点,提供读扩展和高可用 |
| 索引/文档/字段 | 对标 MySQL 库表行列 | Mapping 要提前定义,text vs keyword 必须区分 |
| 倒排索引 | 词 → 文档 ID 列表的高效查找结构 | 分词器的选择影响搜索质量,中文必须用 IK |
| 写入流程 | 协调→主分片→副本→响应 | 深翻页问题、quorum 一致性要理解 |
| NRT / refresh | 写后 1 秒内可搜索 | refresh_interval=-1 是批量写优化必备 |
| flush + translog | 持久化保证 + 崩溃恢复 | translog 不清空会撑爆磁盘,flush 成功才真正安全 |

相关推荐
德昂信息dataondemand1 小时前
BI项目中的主数据管理:如何确保跨部门数据一致性?
大数据
申通之声2 小时前
以体验和AI重构竞争力,申通要“构建生态共同体”
大数据·网络·人工智能·重构·交通物流
terry6002 小时前
2026图形验证码服务商横向测评|口碑、接入、安全选型全指南
java·大数据·人工智能·web安全·信息与通信·数据库架构
量化君也2 小时前
从回测到全自动实盘交易,全天候策略需要经历哪些改造?
大数据·人工智能·python·算法·金融
KaMeidebaby3 小时前
卡梅德生物技术快报|纳米抗体表达:分子生物学实操指南:噬菌体筛选与纳米抗体表达全流程技术拆解
大数据·人工智能·架构·spark·新浪微博
zhengzhouliuhaha3 小时前
智能医疗设备控费系统:以全院一体化管控,筑牢医疗资源“安全阀”
大数据·数据结构·人工智能·算法·安全·机器学习·软件需求
云边云科技_云网融合4 小时前
共建智能体互联网新生态|云边云科技亮相智能体互联网生态共建大会
大数据·人工智能
智能化咨询4 小时前
(105页PPT)智慧商圈解决方案(附下载方式)
大数据
X1A0RAN4 小时前
Jenkins流水线日志彩色打印输出
运维·jenkins