ElasticSearch 最佳实践
目录
- 索引设计
- Mapping 设计
- 写入优化
- 搜索优化
- 分片与节点规划
- 运维与监控
- 常见反模式
- 安全与稳定性
- 日志/搜索/电商三类场景最佳实践
理由:
- 分片太大:迁移困难,恢复慢
- 分片太小:shard 过多(浪费内存)
推荐:
总数据量 / 40GB = 推荐 shard 数量
不要把日志全部写入 logs 索引。
正确:
logs-2025.01.01
logs-2025.01.02
配合 ILM 自动 rollover。
action.auto_create_index: false
避免野生索引,避免 mapping 爆炸。
ES 的 field 越多,内存越高、查询越慢。
限制:
"index.mapping.total_fields.limit": 1000
"title": {
"type": "text",
"fields": {
"raw": { "type": "keyword" }
}
}
用途:
- title 做全文搜索
- title.raw 做排序、聚合
错误(非常损性能):
"status": "text"
正确:
"status": "keyword"
所有枚举类字段都用 keyword。
如果可以:
- 用对象数组替代
- 或者扁平化结构(denormalization)
"dynamic": "strict"
减少字段爆炸 + 防止垃圾数据污染索引。
每批 1k–5k 文档最佳。
默认 1s 刷新太频繁,写入吞吐下跌。
日志类场景:
"refresh_interval": "30s"
普通业务:
"refresh_interval": "5s"
高写入场景(如导入大量数据):
number_of_replicas: 0
导入完成后再改回:
number_of_replicas: 1
写密集型应用:
index.translog.durability: async
index.translog.sync_interval: 30s
吞吐量极大提升。
"bool": {
"filter": [
{"term": {"status": "active"}}
]
}
filter 查询性能极高,搜索缓存命中多。
有以下情况请选择:
| 场景 | 替代方式 |
|---|---|
| 前缀匹配 prefix | edge_ngram |
| 模糊查询 | fuzzy(有限度) |
| 模糊匹配 | ngram |
不要:
from: 200000
改用:
- search_after
- 或者 scroll(导出大量数据)
text 字段不能聚合。
提高主字段评分:
"match": {
"title": {
"query": "python",
"boost": 3
}
}
症状:
- JVM heap 爆高
- 集群变慢
- 集群恢复时间过长
原则:
- 只分够接下来 1 年的量,不要多
- 每节点 shard 数 ≤ 20 × CPU 核数(经验值)
| 场景 | 副本数 |
|---|---|
| 日志写入高峰 | 0 |
| 正常业务 | 1 |
| 高读取量 | 2–3 |
bootstrap.memory_lock: true
不要超过 32GB(否则关闭压缩指针,性能直线下降)。
ES 对磁盘 IO 非常敏感。
自动:
- rollover
- warm / cold / frozen
- delete
快照恢复是分布式集群核心能力。
生产必须分离:
- master
- data
| ❌ 反模式 | 原因 |
|---|---|
| 一个索引几百 GB | 分片迁移慢,恢复慢 |
| 全字段 dynamic mapping | 字段爆炸 |
| 搜索用 wildcard “*” 前缀 | 全表扫描 |
| from=100000 深分页 | 慢死 |
| 所有字段都 text | 聚合、排序无效 |
| keyword 做全文搜索 | 匹配不到 |
| JVM heap > 32GB | 禁用压缩指针 |
| 一个节点 1000 shard | OOM 风险 |
- 启用 xpack.security
- HTTPS 传输
- API key 管理服务之间权限
- 索引级别权限
- Kibana + Spaces + RBAC
- index 按天滚动
- refresh_interval = 30s
- replicas = 0(高峰)
- keyword 用于聚合
- 禁止 wildcard 全模糊
- 使用 ILM
- 标题 text + keyword.raw
- 分类 keyword
- 价格 range + 数字类型
- 日期 date
- 使用 search_after 分页
- 使用 HNSW(ES8 默认)
- 维度 ≤ 2048
- 使用 knn 查询