Elasticsearch(ES)是一个基于 Lucene 的分布式搜索引擎,它的设计精髓在于一切为了搜索性能 。
但想要用好 ES,必须先理解它的核心概念 和系统架构。很多新手在使用 ES 时遇到的性能问题、数据丢失问题、扩容问题,根源往往在于对分片、副本、分配等机制理解不够深入。
1. 核心概念
在进入细节之前,先看一张 ES 与关系型数据库的对照表,帮助你快速建立映射:
| ES 7.x 以前 | ES 7.x 及以后 | MySQL |
|---|---|---|
| Index | Index | Database |
| Type | _doc(默认) |
Table |
| Document | Document | Row |
| Field | Field | Column |
| Mapping | Mapping | Schema |
| Shards | Shards | 分区 / 分表 |
| Replicas | Replicas | 备份/只读副本 |
2. 索引(Index)
2.1 定义
索引是具有相似特征的文档集合。你可以把它理解为关系型数据库中的"数据库"。
例如:
- 客户索引(customer)
- 商品索引(product)
- 订单索引(order)
2.2 命名规范
- 必须全部小写字母
- 不能包含
\ / * ? " < > | , # :等特殊字符 - 建议使用下划线分隔,如
user_logs_2026
2.3 索引的本质
能搜索的数据必须被索引。
我们可以把索引类比为新华字典的目录:
- 目录(索引)的存在,让你能快速找到某个汉字在哪一页。
- 如果没有目录,你只能一页一页翻(全表扫描),效率极低。
ES 的索引底层是倒排索引(Inverted Index) ,它是一种词条 → 文档列表的映射结构,使得全文搜索可以达到毫秒级响应。
2.4 设计哲学
Elasticsearch 索引的精髓:一切设计都是为了提高搜索的性能。
这意味着:
- 索引不是"存储"结构,而是"检索"结构。
- 存储数据只是手段,快速找到数据才是目的。
- 因此,ES 宁愿牺牲一些写入性能,也要保证查询性能。
3. 类型(Type)
3.1 概念
Type 是 Index 内部的逻辑分类,类似于数据库中的"表"。
例如,在 blog 索引中,你可以有:
blog/article(文章)blog/comment(评论)
3.2 版本演进(非常关键!)
| ES 版本 | Type 支持情况 |
|---|---|
| 5.x | 支持多种 Type |
| 6.x | 一个 Index 只能有一个 Type |
| 7.x | 彻底移除自定义 Type,统一使用 _doc |
3.3 为什么要移除 Type?
- 同一 Index 下不同 Type 的相同字段,在 Lucene 底层是共享同一个字段存储的,容易造成映射冲突。
- 随着时间推移,官方认为 Type 带来的复杂性大于收益。
- 因此 ES 7.x 起,所有文档都使用
_doc作为默认 Type。
💡 如果你还在使用 ES 6.x 及以下版本,建议尽快升级。
4. 文档(Document)
4.1 定义
文档是 ES 中可被索引的基本信息单元,也就是一条 JSON 数据。
示例:
json
{
"id": 1001,
"name": "zhangsan",
"age": 25,
"tags": ["engineer", "beijing"]
}
4.2 文档的特点
- 使用 JSON 格式,是互联网最通用的数据交换格式。
- 每个文档都有一个唯一的
_id(可自动生成或手动指定)。 - 文档是不可变的:每次更新实际上是创建了一个新版本,旧版本被标记为删除。
4.3 文档的元数据
| 字段 | 说明 |
|---|---|
_index |
文档所属索引 |
_type |
文档所属类型(7.x 为 _doc) |
_id |
文档唯一标识 |
_version |
版本号,每次修改 +1 |
_seq_no |
序列号,用于并发控制 |
_source |
文档原始 JSON 内容 |
5. 字段(Field)
字段是文档中的属性键值对,类似于 MySQL 的列。
每个字段都有:
- 数据类型(text、keyword、long、date 等)
- 是否索引(index: true / false)
- 是否存储(store: true / false)
⚠️ 注意:即使
store为 false,字段内容也会存在于_source中,只是不会独立存储。
6. 映射(Mapping)
6.1 定义
Mapping 相当于 MySQL 中的表结构定义,它规定了:
- 字段的数据类型
- 是否索引
- 使用什么分词器
- 是否支持排序/聚合
6.2 动态映射 vs 显式映射
- 动态映射:ES 会自动推断字段类型(适合快速原型开发)。
- 显式映射:手动定义字段属性,推荐用于生产环境(性能更好、更可控)。
6.3 Mapping 示例
json
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"price": {
"type": "double"
},
"is_active": {
"type": "boolean"
}
}
}
}
6.4 Mapping 的设计原则
- 字段越少越好:不必要的字段不要索引。
- 选择合适的类型 :如不需要分词的字段用
keyword而非text。 - 关闭不需要的索引 :
"index": false可节省存储和提升写入速度。
7. 分片(Shards)
7.1 为什么需要分片?
单个节点无法存储海量数据,或者单个节点处理请求太慢。
ES 通过将索引水平切分为多个分片,来解决这些问题。
7.2 分片的本质
一个分片 = 一个 Lucene 索引实例。
也就是说,你在 ES 中创建一个索引,实际上是在多个节点上创建了多个 Lucene 索引。
7.3 分片的作用
- 水平扩展:数据可以分布到多台机器。
- 并行处理:搜索请求可以并发执行,提高吞吐量。
7.4 分片数量如何确定?
text
分片数 = 总数据量 / 单分片容量(建议 20GB ~ 50GB)
- ES 7.x 默认主分片数为 1(早期版本为 5)。
- 分片数一旦创建不可修改,所以要提前规划。
7.5 分片并非越多越好
| 问题 | 说明 |
|---|---|
| 元数据开销 | 每个分片都有独立的元数据,过多会增加集群管理负担 |
| 查询延迟 | 查询需要访问所有分片,分片过多会增加协调开销 |
| 故障恢复慢 | 分片越多,节点故障时恢复时间越长 |
✅ 建议:单个分片数据量控制在 20GB ~ 50GB,分片总数控制在节点数 × 20 以内。
8. 副本(Replicas)
8.1 定义
副本是主分片的完整拷贝,用于提供高可用性和扩展读能力。
8.2 副本的作用
- 高可用:当主分片所在的节点宕机,副本可以提升为主分片。
- 提升读性能:搜索请求可以分摊到所有副本上并行执行。
8.3 副本数量配置
json
{
"settings": {
"number_of_replicas": 1 // 默认为 1
}
}
8.4 副本数量可以动态调整
http
PUT /my_index/_settings
{
"number_of_replicas": 2
}
8.5 副本与主分片的关系
- 副本永远不会与主分片落在同一个节点上。
- 写入请求只会发往主分片,主分片同步给所有副本(同步或异步)。
9. 分配(Allocation)
9.1 定义
分配是指将分片(主分片或副本)指派到某个具体节点的过程。
9.2 谁负责分配?
集群中的 Master 节点负责统一调度分配决策。
分配时会考虑:
- 磁盘空间
- 节点负载
- 分片均衡策略
- 机架感知(rack awareness)
9.3 常用分配策略
json
{
"settings": {
"cluster.routing.allocation.awareness.attributes": "rack_id"
}
}
这样 ES 会尽量将副本分配到不同的机架,防止机架级故障。
10. 系统架构深入
10.1 节点(Node)
一个运行中的 ES 实例就是一个节点。
节点通过 cluster.name 配置加入同一个集群。
10.2 集群(Cluster)
由多个节点组成,共同承担数据存储和查询压力。
10.3 主节点(Master Node)
- 负责管理集群层面的变更:创建/删除索引、添加/移除节点。
- 不参与文档级别的读写操作。
- 任何节点都可以被选为主节点。
10.4 数据节点(Data Node)
- 存储分片数据。
- 执行文档的 CRUD 和搜索操作。
10.5 协调节点(Coordinating Node)
- 接收客户端请求。
- 将请求路由到相关数据节点。
- 汇总并返回结果给客户端。
10.6 一个请求的完整流程
text
客户端 → 协调节点 → 路由到主分片/副本 → 执行操作 → 返回结果
ES 对这一切的管理都是完全透明的,你只需要向任意节点发送请求即可。
11. 一张图总结 ES 架构


12. 生产环境最佳实践建议
| 建议项 | 说明 |
|---|---|
| 分片数规划 | 提前评估数据量,创建后不可改 |
| 副本数设置 | 至少 1,保证高可用 |
| 节点角色分离 | 主节点不存数据,数据节点不参与选举 |
| 监控磁盘 | 磁盘使用率超过 85% 会影响分配 |
| 合理设置刷新间隔 | refresh_interval 默认 1s,可适当调大以提升写入性能 |
✅ 总结
| 概念 | 一句话理解 |
|---|---|
| Index | 数据库 |
| Type | 表(7.x 已弃用) |
| Document | 一行数据 |
| Field | 一列数据 |
| Mapping | 表结构定义 |
| Shard | 数据分片,水平扩展的基础 |
| Replica | 主分片的备份,高可用 + 读扩展 |
| Allocation | 分片分配到节点的过程 |
| Master Node | 集群的管理者 |
| Data Node | 数据的存储者 |