Elasticsearch 核心概念与系统架构详解

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 分片的作用

  1. 水平扩展:数据可以分布到多台机器。
  2. 并行处理:搜索请求可以并发执行,提高吞吐量。

7.4 分片数量如何确定?

text 复制代码
分片数 = 总数据量 / 单分片容量(建议 20GB ~ 50GB)
  • ES 7.x 默认主分片数为 1(早期版本为 5)。
  • 分片数一旦创建不可修改,所以要提前规划。

7.5 分片并非越多越好

问题 说明
元数据开销 每个分片都有独立的元数据,过多会增加集群管理负担
查询延迟 查询需要访问所有分片,分片过多会增加协调开销
故障恢复慢 分片越多,节点故障时恢复时间越长

✅ 建议:单个分片数据量控制在 20GB ~ 50GB,分片总数控制在节点数 × 20 以内。


8. 副本(Replicas)

8.1 定义

副本是主分片的完整拷贝,用于提供高可用性和扩展读能力。

8.2 副本的作用

  1. 高可用:当主分片所在的节点宕机,副本可以提升为主分片。
  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 数据的存储者

相关推荐
向日的葵0063 小时前
Redis会话机制vsJWT机制深度解析
数据库·redis·python·缓存·系统架构·jwt
风行無痕3 小时前
单机Elasticsearch 8.19.18安全升级到9.4.3的过程
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客5 小时前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
大数据·运维·前端·人工智能·elasticsearch·搜索引擎·全文检索
阿拉雷️6 小时前
【搜索实战】Spring Boot 3.3 + AI Agent × Elasticsearch:让AI自动优化搜索策略,查询速度从2秒压到50毫秒
人工智能·spring boot·elasticsearch
Xxtaoaooo17 小时前
DolphinDB 物联网数据平台全景:一份从架构到落地的实践地图
物联网·系统架构·时序数据库·数据库架构·dolphindb
阿里云大数据AI技术20 小时前
阿里云 ES AI 引擎版:面向 Agent 场景,为亿级租户、千亿规模向量设计的搜索引擎
人工智能·elasticsearch·agent
阿里云大数据AI技术21 小时前
FalconSeek 技术解析:阿里云 Elasticsearch 云原生内核如何让查询性能飙升600%
人工智能·elasticsearch
Elastic 中国社区官方博客21 小时前
将你的 Grafana Kubernetes 仪表板迁移到 Elastic Observability:相同的 PromQL,30 倍更快的查询
大数据·人工智能·elasticsearch·搜索引擎·容器·kubernetes·grafana
Elasticsearch1 天前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
elasticsearch