Elasticsearch核心概念详解
一、什么是Elasticsearch?
Elasticsearch是一个开源的分布式、RESTful风格的搜索和分析引擎,基于Apache Lucene构建。它能够以近实时的方式存储、搜索和分析海量数据,广泛应用于全文检索、日志分析、实时监控、商业智能等场景。
核心特点:
- 分布式架构:数据自动分片存储在多台服务器上,支持水平扩展
- 近实时搜索:从数据写入到可搜索的延迟通常在1秒以内
- RESTful API:所有操作通过HTTP API完成,简单易用
- 多租户支持:支持多个索引,每个索引可以独立配置
- 文档导向:数据以JSON文档形式存储,无需预定义schema
二、核心术语体系
1. 文档(Document)
定义:Elasticsearch中最小的数据单元,以JSON格式存储。每个文档代表一个可被索引的数据记录。
示例:
{
"id": 1,
"title": "Elasticsearch入门指南",
"content": "这是一篇关于Elasticsearch的入门文章...",
"author": "张三",
"create_time": "2025-12-22T10:30:00",
"tags": ["elasticsearch", "搜索", "教程"]
}
关键特性:
- 每个文档都有唯一的
_id字段,可以自动生成或手动指定 - 文档是索引和搜索的基本单位
- 支持嵌套对象和数组类型
2. 索引(Index)
定义:具有相似特征的文档集合,类似于关系型数据库中的”表”。
示例:
books索引:存储所有图书信息logs索引:存储系统日志products索引:存储商品信息
关键特性:
- 每个索引可以独立配置映射、分片、副本等参数
- 索引名称必须小写,不能包含特殊字符
- 支持按时间创建滚动索引(如
logs-2025.12.22)
3. 类型(Type,已弃用)
历史背景:在Elasticsearch 7.x之前,一个索引可以包含多个类型,类似于关系型数据库中的”表”。但从7.0版本开始,类型已被弃用,8.0版本完全移除。
弃用原因:
- 类型在Lucene层面没有实际意义,导致性能开销
- 不同类型的数据存储在同一个索引中,容易产生映射冲突
- 简化数据模型,一个索引只包含一种文档类型
4. 映射(Mapping)
定义:定义索引中字段的类型和属性,类似于关系型数据库中的”表结构”。
示例映射:
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"author": {
"type": "keyword"
},
"price": {
"type": "float"
},
"create_time": {
"type": "date"
}
}
}
}
映射类型:
- 动态映射:自动根据文档字段推断类型
- 显式映射:手动定义字段类型和属性
- 模板映射:通过索引模板自动应用映射规则
5. 分片(Shard)
定义:索引的物理存储单元,一个索引可以被分成多个分片,分布在不同的节点上。
主分片 vs 副本分片:
- 主分片(Primary Shard):存储索引数据的主副本,负责写入操作
- 副本分片(Replica Shard):主分片的副本,提供数据冗余和读负载均衡
配置示例:
{
"settings": {
"number_of_shards": 5, // 主分片数量
"number_of_replicas": 1 // 每个主分片的副本数量
}
}
分片策略:
- 主分片数量在创建索引时确定,后续不能修改
- 副本分片数量可以动态调整
- 每个分片都是一个独立的Lucene索引
6. 节点(Node)
定义:运行Elasticsearch实例的服务器,是集群的基本组成单元。
节点类型:
- 主节点(Master Node):负责集群管理、索引创建、分片分配等元数据操作
- 数据节点(Data Node):存储数据分片,处理数据读写请求
- 协调节点(Coordinating Node):接收客户端请求,分发到数据节点,聚合结果
- 摄取节点(Ingest Node):在索引前对文档进行预处理
- 机器学习节点(ML Node):运行机器学习作业
7. 集群(Cluster)
定义:由一个或多个节点组成的集合,共同存储数据并提供搜索服务。
集群状态:
- Green:所有主分片和副本分片都正常
- Yellow:所有主分片正常,但部分副本分片异常
- Red:部分主分片异常,数据可能丢失
三、倒排索引原理
基本概念
倒排索引(Inverted Index)是Elasticsearch实现快速全文检索的核心技术,它将文档中的每个词项映射到包含该词项的文档列表。
示例:
文档1:I love Elasticsearch
文档2:Elasticsearch is powerful
文档3:I love learning
倒排索引:
I → [文档1, 文档3]
love → [文档1, 文档3]
Elasticsearch → [文档1, 文档2]
is → [文档2]
powerful → [文档2]
learning → [文档3]倒排索引结构
词项字典(Term Dictionary):
- 存储所有不重复的词项
- 按字典序排序,便于二分查找
倒排列表(Posting List):
- 存储包含该词项的文档ID列表
- 包含词频、位置等信息
跳表(Skip List):
- 加速倒排列表的合并操作
- 在长倒排列表中快速定位
查询过程
- 词项解析:将查询字符串分词为词项列表
- 查找词项:在词项字典中查找每个词项
- 获取文档列表:获取每个词项的倒排列表
- 合并结果:根据查询逻辑(AND/OR)合并倒排列表
- 相关性打分:计算文档与查询的相关性得分
- 返回结果:按得分排序返回文档
四、近实时(NRT)搜索机制
写入流程
- 写入请求:客户端发送文档到协调节点
- 路由到分片:根据文档ID路由到对应的主分片
- 写入内存缓冲区:文档写入到主分片的内存缓冲区
- 写入事务日志(translog):同时写入事务日志,保证数据持久化
- refresh操作:默认每1秒执行一次,将内存缓冲区的内容刷新到新的段(segment)
- 段可搜索:refresh后新文档可以被搜索到
- flush操作:将内存中的段写入磁盘,清空事务日志
refresh机制
refresh间隔:默认1秒,可以通过以下方式调整:
- 动态调整:
PUT /index/_settings { "refresh_interval": "30s" } - 强制refresh:
POST /index/_refresh - 关闭refresh:
PUT /index/_settings { "refresh_interval": -1 }
性能影响:
- 频繁refresh会增加IO压力,降低写入性能
- 过长的refresh间隔会延迟搜索可见性
段合并(Segment Merge)
背景:每次refresh都会生成新的段,导致段数量增多,影响搜索性能。
段合并过程:
- 后台线程定期选择多个小段合并成更大的段
- 合并过程中,被合并的段仍然可以被搜索
- 合并完成后,删除旧的小段
优化策略:
- 强制合并:
POST /index/_forcemerge?max_num_segments=1 - 避免在写入高峰期执行段合并
五、核心概念关系图
集群(Cluster)
├── 节点(Node)
│ ├── 主节点(Master Node)
│ ├── 数据节点(Data Node)
│ └── 协调节点(Coordinating Node)
│
└── 索引(Index)
├── 映射(Mapping)
├── 分片(Shard)
│ ├── 主分片(Primary Shard)
│ └── 副本分片(Replica Shard)
│
└── 文档(Document)
└── 字段(Field)六、最佳实践
1. 索引设计
- 按业务场景划分索引,避免单个索引过大
- 合理设置主分片数量(建议每个分片20-50GB)
- 使用索引别名,便于索引重建和滚动更新
2. 映射设计
- 提前定义显式映射,避免动态映射导致字段类型冲突
- 合理选择字段类型:text用于全文搜索,keyword用于精确匹配
- 关闭不需要索引的字段:
"index": false
3. 写入优化
- 使用批量API(_bulk)减少网络开销
- 调整refresh间隔,批量写入时设置为-1,写入完成后手动refresh
- 使用自动生成的文档ID,避免路由计算开销
4. 查询优化
- 使用filter查询缓存结果
- 避免深度分页,使用search_after替代from/size
- 合理使用聚合查询,避免内存溢出
七、总结
Elasticsearch的核心概念体系是理解和使用该技术的基础。文档、索引、映射、分片、节点等概念构成了Elasticsearch的数据模型,倒排索引和近实时搜索机制是其高性能的保障。掌握这些核心概念,能够帮助开发者更好地设计索引结构、优化查询性能、规划集群架构,从而构建高效可靠的搜索和分析系统。
最后编辑:严锋 更新时间:2025-12-25 10:39