Elasticsearch 知识体系手册
本手册基于多 Agent 并行检索 + 主 Agent 汇总生成,涵盖 Elasticsearch 核心概念与架构、索引搜索 API、性能优化、集群管理、生态集成、生产最佳实践六大维度,适用于学习回顾与生产参考。
一、核心概念与架构
1.1 倒排索引底层原理
Elasticsearch 基于 Apache Lucene,每个 shard 就是一个 Lucene 索引。
核心数据结构:
Term Dictionary(term → docFreq + pointer)
↓
Posting List(docID, freq, positions)
- Lucene 不存原文,只存每个词出现在哪些文档(docID 列表)+ 词频/位置
- FST(Finite State Transducer):term dictionary 的存储结构,类似前缀树但更紧凑,内存占用比 HashMap 低 50%+
- Posting List 压缩:Lucene 使用 FOR(Frame of Reference)或 PFOR(Patched FOR)编码,将 docID 列表差分存储,大幅节省空间
Doc Values 列式存储:
- 倒排索引加速搜索,Doc Values 加速排序/聚合
- Doc Values 在索引时构建,按列存储,与倒排互补
- text 类型无 Doc Values,这是 text 不能排序/聚合的根本原因
Segment 机制:
- 每个 shard 的数据由多个 segment 组成,写入新文档时先写内存 buffer,定期生成新 segment(refresh,默认 1s)
- Segment 是不可变的(immutable),删除不物理删除,而是记录一个
del文件(live docs bitmap)标记删除 - 段合并时物理清理已删除文档,合并成更大段
1.2 分片与副本(Sharding & Replication)
| 概念 | 说明 |
|---|---|
| Primary Shard | 索引数据分配的单位,创建后数量不可变(除非 reindex) |
| Replica Shard | Primary 的副本,支持主副本同步,提供高可用和查询吞吐 |
分片策略原则:
- 每个分片建议 10~50 GB 数据
- 分片数过小 → 数据量大时单片过大,查询慢
- 分片数过大 → 过多小 segment,内存压力大
- 计算公式:
primary_shards = data_nodes * (1~2)(写入密集场景取上限)
1.3 集群发现与选主(Discovery & Master Election)
- ES 7.x 默认使用 zen2 协议(可切换为 EC2/Azure/GCP 云发现)
- Bootstrap Checks:启动时严格检查各项配置(heap size、memory lock、file descriptors 等)
- minimum_master_nodes:防止脑裂,推荐设为
(master_eligible_nodes / 2) + 1 - 选主流程:PING 探测 → 节点列表排序 → Bully 算法选中最高 node_id
1.4 数据写入流程
写入路径:Client → Coordinating Node → Primary Shard → Replica Shard → Response
- 请求先到 Coordinating Node,根据
_routing计算目标 shard - 写入 Primary Shard 的 memory buffer + translog(同步追加)
- Primary 成功后并行转发到所有 Replica Shard
- 当 translog
flush_threshold_size达到阈值或sync_interval到期,触发 lucene commit,生成新 segment
二、索引与搜索 API
2.1 Mapping 配置
{
"mappings": {
"dynamic": "strict",
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": { "type": "keyword" }
}
},
"price": { "type": "scaled_float", "scaling_factor": 100 },
"location": { "type": "geo_point" },
"tags": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}
关键配置说明:
| 参数 | 选项 | 说明 |
|---|---|---|
dynamic |
strict / true / false |
strict 拒绝未知字段,false 忽略,true 自动推断 |
fields |
子字段机制 | 解决 text 类型无法排序/聚合的问题 |
scaled_float |
比 double 省空间 | 适合价格类数据,配合 scaling_factor 使用 |
doc_values |
true / false |
关闭可省 heap,适用于不需要排序/聚合的字段 |
2.2 Query DSL 分类
| 类别 | 常见 Query | 特点 |
|---|---|---|
| 全文查询 | match, multi_match, query_string |
参与相关性评分,会被分析 |
| 精确查询 | term, terms, range |
不分析,精准匹配 |
| 复合查询 | bool(must/should/filter/must_not) |
组合多条件 |
| 地理查询 | geo_distance, geo_bounding_box |
基于地理位置过滤 |
重要原则:bool filter 不计算 score,且会被缓存;bool must 参与评分。优先用 filter 而非 must(除非需要相关性排序)。
2.3 聚合(Aggregations)
| 类型 | 代表 | 用途 |
|---|---|---|
| Bucket 聚合 | terms, histogram, date_range |
按条件分组 |
| Metric 聚合 | avg, sum, max, min, cardinality |
计算指标 |
| Pipeline 聚合 | bucket_sort, cumulative_sum, moving_avg |
对聚合结果再加工 |
实战技巧:
- 查询结果不需要 hits 时设
size: 0,提升性能 - 高基数字段用
composite聚合做分页,避免深度分页
2.4 Analyze 分析器
分词器由三级组成:Character Filter → Tokenizer → Token Filter
| 组件 | 作用 | 示例 |
|---|---|---|
| Character Filter | 原始文本预处理 | html_strip 去除 HTML 标签 |
| Tokenizer | 分词 | standard(按空格/标点)、ik_max_word(中文最大切分) |
| Token Filter | 分词后处理 | lowercase、synonym(同义词)、pinyin(拼音) |
三、性能优化
3.1 JVM Heap 配置
- Heap 大小 ≤ 50% 物理内存,不超过 ~30.5 GB(Compressed OOPs 临界点)
- 配置示例:
-Xms31g -Xmx31g(ms与mx必须相同,防止堆调整抖动) - 禁用 swap:
bootstrap.memory_lock: true - GC 推荐 G1GC:ES 7.x 默认,
-XX:MaxGCPauseMillis=200 - 监控指标:
node_stats.jvm.mem.heap_used_percent保持在 75% 以下
3.2 Refresh 与 Translog 调优
| 场景 | refresh_interval | translog.durability |
|---|---|---|
| 批量导入期间 | -1(关闭) |
async |
| 正常写入 | 1s(默认) |
request |
translog.sync_interval:默认5s,设为更大值可提升写入吞吐translog.flush_threshold_size:默认 512MB,触发 Lucene commit
3.3 段合并策略
- 合并策略:
TieredMergePolicy(ES 7.x 默认) - 关键参数:
index.merge.scheduler.max_thread_count:HDD 或写入密集期设为 1index.merge.policy.segments_per_tier:默认 10,越大合并越少、查询越慢
3.4 Filter 缓存机制
bool filter查询结果缓存在 Node Query Cache(默认 10% heap)- 缓存粒度为 segment 级别的 bitset,segment 变更时对应 filter cache 失效
- 提高命中率:多用 filter 代替 must、按时间冷热分离索引减少 segment 变更频率
3.5 Bulk 批量写入
- 推荐大小:5~15 MB 或 5,000~15,000 文档/请求
- 并发控制:写入线程数 ≤
0 + number_of_shards * 5,超出触发 429 限流 - 写入期间:
refresh_interval: -1,写入完成后POST /_refresh手动刷新
四、集群管理与安全
4.1 节点类型
| 节点类型 | node.master | node.data | node.ingest | 说明 |
|---|---|---|---|---|
| Master | true | false | false | 集群元数据管理 |
| Data | false | true | - | 数据存储与查询 |
| Ingest | false | false | true | 数据预处理(pipeline) |
| Coordinating | false | false | false | 路由转发,分担查询压力 |
生产环境推荐:3 个专用 Master 节点 + 若干 Data 节点 + 若干 Coordinating 节点
4.2 故障转移流程
- 节点宕机检测(PING 超时,默认
ping_timeout: 3s,ping_retries: 3) - Master 触发 副本升级:缺失副本的 Primary 对应 replica 升级为 primary
- 若有多个副本同时故障,集群状态变为
red - 恢复期间写入请求会被拒绝(
429),读取仍可在健康副本上执行
4.3 跨集群复制(CCR)
- 原理:Leader index → Follower index(只读),基于 Lucene 索引级别同步
- 适用场景:异地灾备、多数据中心同步
PUT /my-follower/_ccr/follow
{ "remote_cluster": "leader-cluster", "leader_index": "my-index" }
4.4 安全配置(X-Pack Security)
- 认证:支持 Basic / LDAP / PKI / SAML / OIDC
- 通信加密:TLS/SSL 加密集群内部和外部通信
- 角色与权限:基于角色的访问控制(RBAC),可精确到 field / document level
4.5 集群健康与故障排查
| 状态 | 含义 |
|---|---|
| green | 所有主副本分片已分配 ✅ |
| yellow | 所有主分片已分配,但有副本未分配 ⚠️ |
| red | 有主分片未分配 🚨 |
常用监控 API:
# 集群健康
GET /_cluster/health?level=indices
# 查看分片未分配原因
GET /_cluster/allocation/explain?pretty
# 节点统计
GET /_nodes/stats
五、与大数据生态集成
5.1 ELK Stack 架构
[数据源] → [Beats/Logstash 采集] → [Elasticsearch 存储索引] → [Kibana 可视化]
| 组件 | 职责 | 特点 |
|---|---|---|
| Beats | 轻量级数据采集 | Filebeat(日志)、Metricbeat(指标)、Packetbeat(网络) |
| Logstash | 数据清洗转换 | ETL pipeline,支持 filter/grok 解构日志 |
| Elasticsearch | 存储与搜索 | 分布式全文检索 + 聚合分析 |
| Kibana | 可视化与探索 | 仪表板、Graph 图分析、Machine Learning |
5.2 Beats 选型
| Beat | 用途 | 典型场景 |
|---|---|---|
| Filebeat | 日志文件收集 | nginx/access.log、application.log |
| Metricbeat | 系统/服务指标 | CPU、内存、网络、Redis/MySQL 指标 |
| Packetbeat | 网络抓包 | HTTP、DNS、MySQL 协议分析 |
| Heartbeat | 站点可用性监测 | 定时 ping 检测服务存活 |
| Auditbeat | 安全审计 | 文件完整性、用户登录事件 |
5.3 与 Spark / Flink 集成
Spark → ES:
spark.write.format("org.elasticsearch.spark.sql")
.option("es.nodes", "localhost:9200")
.save("index-name")
- Flink → ES:Flink ES Connector 支持实时流写入
- ES → Spark:通过
es-spark-connector读取 ES 索引作为 Spark 数据源
六、生产最佳实践
6.1 冷热数据分离架构
Hot Node(SSD)←→ Warm Node(HDD)←→ Cold Node(慢速存储)←→ Frozen Node(只读快照)
- Hot Node:处理当前写入和高频查询,使用高性能 SSD
- Warm Node:索引不再写入但仍需查询,数据量中等
- Cold Node:历史数据,极少查询,使用大容量低成本存储
- Frozen Node:只读快照,按需恢复,成本最低
6.2 ILM 索引生命周期管理
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": { "rollover": { "max_age": "7d", "max_size": "50GB" } }
},
"warm": {
"min_age": "30d",
"actions": { "shrink": { "number_of_shards": 1 }, "forcemerge": { } }
},
"cold": {
"min_age": "90d",
"actions": { "allocate": { "require": { "data": "cold" } } }
},
"delete": {
"min_age": "365d",
"actions": { "delete": { } }
}
}
}
}
6.3 快照备份与恢复
# 创建快照
PUT /_snapshot/my_backup/snapshot_20260101
{ "indices": "my-index-*", "include_global_state": false }
# 恢复快照
POST /_snapshot/my_backup/snapshot_20260101/_restore
支持的仓库类型:fs(共享文件系统)、s3、gcs、azure
6.4 Mapping 设计常见陷阱
| 陷阱 | 后果 | 正确做法 |
|---|---|---|
| text 字段用于排序/聚合 | 报错或性能差 | 用 fields 加 keyword 子字段 |
| 动态映射导致字段类型失控 | 磁盘膨胀、查询不准 | 生产用 dynamic: strict 或显式映射 |
| 分片数设置过大 | 内存压力大,rebalance 慢 | 预估数据量,单分片控制在 10~50GB |
未设置 doc_values: false |
对不需要排序/聚合的字段浪费内存 | 对不需要排序的 text 字段关闭 doc_values |
| 使用默认分词器处理中文 | 中文被逐字分割,搜索效果差 | 使用 ik、jieba、pinyin 等中文分词器 |
6.5 容量规划参考
| 数据规模 | Primary Shards | Replicas | Heap 配置 |
|---|---|---|---|
| < 50 GB | 1 | 1 | 8~16 GB |
| 50~200 GB | 3~5 | 1 | 16~32 GB |
| 200 GB~1 TB | 5~10 | 1~2 | 32 GB |
| > 1 TB | 按需分 index + ILM | 1~2 | 32~64 GB |
七、补充知识点
7.1 深度分页方案对比
| 方案 | 原理 | 适用场景 | 限制 |
|---|---|---|---|
| From/Size | 将 from+size 文档全部加载内存排序 | from < 10000 的浅分页 |
深分页内存爆炸,禁止用于大 offset |
| Search_after | 基于游标,sort 字段追踪位置 |
实时数据翻页,推荐方案 | 无法跳页,需配合 PIT 使用 |
| Scroll | 快照上下文保留(ES 8.x 已废弃) | 批量数据导出 | 不适合实时用户界面 |
7.2 Ingest Pipeline
Ingest Node 内置数据预处理管道,可替代 Logstash 轻量级 ETL。
PUT /_ingest/pipeline/my-pipeline
{
"processors": [
{ "json": { "field": "message", "target_field": "parsed" } },
{ "date": { "field": "parsed.timestamp", "formats": ["ISO8601"] } },
{ "remove": { "field": "parsed.raw" } }
]
}
7.3 Reindex 数据迁移
POST /_reindex
{
"source": { "index": "old-index" },
"dest": { "index": "new-index" }
}
⚠️ 数据量大时对集群负载较高,建议在低峰期执行,设置 wait_for_completion: false 异步执行。
7.4 Kibana 高级功能
| 功能 | 说明 |
|---|---|
| Lens | 拖拽式可视化,比传统 Vega 图表更易用 |
| Maps | 地理数据可视化,支持热力图、轨迹图 |
| Machine Learning | 内置异常检测(Anomaly Detection) |
| Graph | 图关系分析,发现实体间的关联关系 |
| Canvas | 像素级定制报表,支持动画和动态数据 |
| Alerting | 基于查询结果设置阈值告警 |
本手册由多 Agent 并行检索 + 主 Agent 汇总生成