ElasticSearch 经典问题
Elasticsearch 的核心问题是「索引设计 + 写放大 + 集群稳定性」
问题
- 写入 ES 后立刻查询,查不到数据
- 与数据库结果不一致
原因
- ES 是 Near Real Time(NRT)
- 默认 refresh_interval = 1s
表现
写入成功 -> 马上查询 -> 结果为空
解决
- 关键路径手动 refresh
- 查询用 DB 做兜底
- 对一致性要求极高的场景 不要直接查 ES
问题
- 字段被自动映射成 text
- keyword / date / number 错误
- 数值被当成字符串
后果
- 无法排序 / 聚合
- 查询性能极差
- 只能重建索引
典型坑
"price": "100" -> text
解决
- 禁用动态 mapping
- 手动定义 mapping
- 版本化索引(index_v1 / v2)
问题
- 分片过多
- 分片过大
- 分片不可修改
后果
- 集群元数据膨胀
- 查询慢
- 恢复慢
经验值
| 指标 | 建议 |
|---|---|
| 单分片大小 | 10GB ~ 50GB |
| 分片数 | ≤ 节点数 × 2~3 |
| 索引数 | 避免百万级 |
问题
from = 100000
size = 10
后果
- 每个 shard 都要排序 + 丢弃
- 内存暴涨
- 查询超时
正确姿势
- search_after
- scroll
- 限制最大分页深度
问题
- terms 聚合字段基数极高
- cardinality、nested 滥用
后果
- JVM 堆内存 OOM
- 节点频繁 GC
解决
- 控制字段基数
- 使用 keyword + doc_values
- 限制聚合层级
问题
- 事务
- 强一致
- join
- update 高频
后果
- 性能差
- 数据错乱
- 运维复杂
原则
ES 是搜索引擎,不是数据库
原因
- segment 不断 merge
- update 实际是 delete + insert
- 副本放大
表现
- 写入 100GB
- 磁盘涨 300GB+
解决
- 合理 refresh_interval
- 减少 update
- 冷热分离 + ILM
典型错误
- heap 设置过大
- 超过 32GB
后果
- 指针压缩失效
- Full GC
- 节点假死
黄金规则
heap = min(32GB, 物理内存 50%)
问题
- master 节点和 data 节点混用
- 网络抖动
后果
- 集群红
- 索引只读
- 服务不可用
解决
- 专用 master 节点
- 奇数个(3 / 5)
- 不承载数据
默认阈值
- 85% -> relocate
- 90% -> 禁止写入(只读)
表现
index read-only / write rejected
恢复方式
PUT _all/_settings
{
"index.blocks.read_only_allow_delete": null
}
原因
- 分片过多
- 分片过大
- 网络带宽不足
影响
- 节点重启 -> 长时间 yellow / red
常见误区
- 以为副本就是备份
- 直接 rsync data 目录
正解
- Snapshot 才是唯一正确备份方式
*abc*
- 全索引扫描
- CPU 飙升
| 维度 | Redis | Elasticsearch |
|---|---|---|
| 核心问题 | 缓存一致性 | 索引设计 |
| 数据一致性 | 弱 | 弱(NRT) |
| 容量问题 | 内存爆 | 磁盘 + heap |
| 扩容风险 | rehash | shard 规划 |
| 高并发 | 单线程 | 多 shard |
| 常见 OOM | 大 key | 聚合 / fielddata |
| 运维复杂度 | 中 | 高 |
Redis 的问题主要集中在缓存一致性和击穿雪崩, 而 Elasticsearch 的问题更多来自索引设计不当、分片规划错误、 JVM 内存和集群稳定性。
在开发阶段需要重点关注 mapping、分页和聚合设计, 在运维阶段要重点关注分片数量、磁盘水位、主节点稳定性以及备份策略。