这是《Elasticsearch 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Elasticsearch 很少单独存在。它通常与 MySQL、Kafka、Redis、对象存储、数据仓库、监控系统和向量模型服务共同工作。架构设计的关键不是把所有数据都放进 ES,而是明确每个系统的职责边界和数据流向。
33.1 Elasticsearch 的定位
Elasticsearch 适合:
- 全文搜索:商品、内容、工单、知识库;
- 日志与可观测性:日志、指标、链路检索;
- 近实时分析:看板、漏斗、多维聚合;
- 地理检索:附近门店、轨迹查询;
- 向量检索:语义搜索、推荐召回、RAG 检索。
不适合:
- 强事务主存储;
- 复杂多表关联和财务对账;
- 高频点查缓存;
- 数据仓库级别复杂 SQL;
- 原始大对象存储;
- 强一致读写。
常见分工:
| 系统 | 职责 |
|---|---|
| MySQL / PostgreSQL | 事务事实来源 |
| Kafka | 变更事件流和缓冲 |
| Redis | 热点缓存和计数 |
| Elasticsearch | 搜索、检索、分析 |
| 对象存储 | 原始文件和快照 |
| 数仓 | 离线建模和精确报表 |
| OLAP 数据库 | 复杂 join 与超宽表分析 |
33.2 搜索投影架构
搜索系统常用 CQRS 思想:命令侧写入数据库,查询侧维护搜索投影。
flowchart LR
A[业务服务] --> B[(MySQL)]
A --> C[Kafka]
C --> D[投影服务]
D --> E[Elasticsearch]
F[搜索 API] --> E
F --> B
投影服务职责:
- 消费领域事件;
- 补齐搜索需要的冗余字段;
- 转换为搜索文档;
- 幂等写入 ES;
- 记录检查点;
- 失败进入重试或死信。
好处:
- 数据库模型不被搜索需求污染;
- ES 可随时重建;
- 写入峰值由 Kafka 缓冲;
- 搜索 Mapping 可以独立演进;
- 业务服务和搜索系统解耦。
代价:
- 数据最终一致;
- 需要处理乱序和重复;
- 需要全量重建能力;
- 增加链路运维复杂度。
33.3 与 MySQL 同步
常见方案:
| 方案 | 延迟 | 复杂度 | 特点 |
|---|---|---|---|
| 双写 | 低 | 中 | 事务一致难,失败补偿复杂 |
| 定时扫描 | 秒到分钟 | 低 | 压力可控,实时性弱 |
| Binlog / CDC | 毫秒到秒 | 中 | 推荐主流方案 |
| 领域事件 | 毫秒到秒 | 中 | 语义清晰 |
| 手动重建 | 小时级 | 低 | 用于全量初始化 |
推荐组合:
初始化:全量扫描 + 版本号
增量:Binlog CDC 或领域事件
校验:定时抽样比对
修复:按主键重放
同步服务必须处理:
- 插入、更新、删除;
- 乱序事件;
- 重复事件;
- Mapping 校验失败;
- ES 写入 429;
- 检查点与数据一致性;
- 全量重建期间切换别名。
33.4 与 Kafka 集成
Kafka 在 ES 架构中承担:
- 日志削峰;
- 业务事件缓冲;
- 写入重放;
- 多消费者分发;
- 上游和下游解耦。
flowchart LR
A[应用] --> K[Kafka]
K --> B[搜索投影]
K --> C[日志写入]
K --> D[流计算]
B --> E[ES]
C --> E
D --> F[(数仓)]
消费设计:
| 问题 | 方案 |
|---|---|
| 峰值 | 消费限流 + 背压 |
| 失败 | 重试 topic + 死信 |
| 重复 | 文档 ID 幂等 |
| 乱序 | 事件版本号 |
| 断点 | offset + checkpoint |
| 监控 | lag、处理耗时、死信数 |
如果 ES 故障 30 分钟,Kafka 可以继续接住上游数据;如果应用直写 ES,则通常只能失败、重试或本地堆积。
33.5 与 Redis 集成
Redis 与 ES 常见配合:
| 场景 | Redis | ES |
|---|---|---|
| 热门搜索词 | 缓存计数 | 搜索词日志分析 |
| 库存或价格 | 高频热点计数 | 搜索展示与过滤 |
| 搜索结果 | 短期缓存 | 召回与排序 |
| 用户画像 | 高频读取 | 多维检索与分群 |
| 限流 | API 计数 | 审计查询 |
不要把高频扣减、下单锁、交易一致性交给 ES。搜索服务可以读 Redis 展示实时价格,但交易仍以数据库为准。
33.6 与数仓和 OLAP
Elasticsearch 和数据仓库的边界:
| 维度 | Elasticsearch | 数仓 / OLAP |
|---|---|---|
| 延迟 | 秒级 | 分钟到小时 |
| Join | 能力有限 | 强 |
| 全文搜索 | 强 | 弱 |
| 灵活聚合 | 强 | 强 |
| 财务精确性 | 需谨慎 | 通常更适合 |
| 历史建模 | 弱 | 强 |
| 明细保留 | 成本高 | 可控 |
典型链路:
业务日志/事件
-> Kafka
-> ES: 近实时排障和看板
-> 数仓: T+1 报表和建模
如果业务同时要求近实时和财务精确,应双写两条链路,而不是强行用一条链路满足两种口径。
33.7 多租户架构
常见隔离方式:
| 方式 | 隔离 | 成本 | 适合 |
|---|---|---|---|
| 单索引共享 | 弱 | 低 | 小客户 |
| 每租户索引 | 中 | 中 | 中等规模 |
| 索引前缀分组 | 中 | 中 | 团队/产品线 |
| 独立集群 | 强 | 高 | 大客户/合规 |
| DLS 权限 | 安全边界 | 低 | 配合索引隔离 |
设计要点:
- 租户 ID 必须进入文档和别名;
- 权限使用 DLS 或索引权限;
- 监控按租户维度统计;
- 禁止通配所有租户索引;
- 大租户可单独迁移;
- 单租户数据倾斜要有隔离方案;
- 备份和保留策略符合合同要求。
33.8 冷热分层
日志和指标类架构:
Hot:最近 0-2 天,高频写入查询
Warm:2-15 天,低频排障
Cold/Frozen:15-90 天,偶尔查询
Delete:到期删除
节点配置:
node.roles: [data_hot]
node.attr.rack: rack-a
索引设置:
PUT logs-app
{
"settings": {
"index.routing.allocation.include._tier_preference": "data_hot"
}
}
分层可以降低成本,但会增加迁移和恢复负载。需要监控:
- ILM 状态;
- rollover 时间;
- shrink 时间;
- segment merge;
- 迁移带宽;
- 冷数据查询延迟。
33.9 在线与离线分离
如果同一个集群同时承担:
- 在线搜索 P99 < 200ms;
- 日志看板任意 30 天聚合;
- 数据团队全量导出;
- 机器学习训练;
- 历史索引重建。
稳定性很难保证。推荐拆分:
在线集群:业务搜索,低延迟
日志集群:观测数据,可接受延迟
离线集群:全量扫描、建模、导出
灾备集群:只读或低流量
分离方式包括:
- 独立集群;
- Kibana 空间与权限限制;
- 时间分区默认查询;
- API 网关限流;
- 大任务进入任务队列低峰执行。
33.10 RAG 检索架构
Elasticsearch 8.x/9.x 常用于 RAG 中的检索层:
flowchart LR
A[用户问题] --> B[Embedding]
B --> C[ES kNN]
A --> D[关键词检索]
D --> C
C --> E[混合召回]
E --> F[Rerank]
F --> G[LLM]
设计要点:
- 文档切块策略比模型更重要;
- 保存 chunk_id、doc_id、version;
- 混合 BM25 和向量召回;
- 使用 RRF 或 rerank 模型融合;
- 过滤权限和过期文档;
- 保存 trace 以便追溯答案来源;
- 评估召回率、答案质量和引用准确性。
向量不是替代关键词,而是补充语义。系统报错码、专有名词、SKU 编号往往关键词检索更可靠。
33.11 自建与云托管
| 维度 | 自建 | 云托管 |
|---|---|---|
| 控制力 | 高 | 中 |
| 运维成本 | 高 | 低 |
| 弹性 | 需自行建设 | 较好 |
| 网络 | 自主规划 | 云内网 |
| 版本升级 | 自控 | 平台控制 |
| 成本模型 | 机器和人力 | 实例和存储 |
| 排障能力 | 需要团队 | 平台支持 |
适合自建:
- 有专职 SRE 团队;
- 有复杂网络和合规要求;
- 数据不能出特定环境;
- 规模大且成本敏感;
- 需要深度定制。
适合托管:
- 团队小;
- 业务迭代优先;
- 缺少 7x24 值班;
- 云内生态已经成熟;
- 快速验证新场景。
无论自建还是托管,快照、权限、容量和监控都不能完全外包给默认值。
33.12 OpenSearch 与 Elasticsearch
OpenSearch 从 Elasticsearch 7.10 分支演化,两者共享大量基础概念,但生态和版本能力逐渐分化。
共同点:
- 文档模型;
- Query DSL 基础;
- Mapping 基础;
- 分片和副本;
- Aggregation 基础;
- Lucene 底层。
差异点:
| 维度 | Elasticsearch | OpenSearch | |
|---|---|---|---|
| 商业归属 | Elastic | OpenSearch 项目 | |
| 高级能力 | ES | QL、托管生态等 | 项目能力持续演进 |
| 客户端 | Java API Client 等 | OpenSearch clients | |
| 插件生态 | Elastic 生态 | OpenSearch 生态 | |
| 版本路线 | 独立演进 | 独立演进 |
迁移前要评估:
- SQL/DSL 兼容性;
- 安全模块差异;
- 索引兼容和 reindex;
- 客户端 SDK;
- 快照格式;
- 监控告警;
- 团队技能和生态依赖。
33.13 架构评审清单
- 数据事实来源在哪里?
- ES 是否可重建?
- RPO/RTO 是否明确?
- 同步链路是否幂等?
- Mapping 和分片是否评审?
- 查询是否有时间范围和索引边界?
- 写入峰值是否有队列缓冲?
- 权限是否按租户或团队隔离?
- 快照和恢复是否演练?
- 监控告警是否覆盖上下游?
- 成本模型是否清楚?
- 是否存在把 ES 当主数据库的隐性依赖?
本章小结
好的 Elasticsearch 架构是“职责清晰的生态系统”:数据库负责事务,Kafka 负责事件流,Redis 负责热点,ES 负责检索和分析,数仓负责复杂建模。设计时应先明确事实来源、数据一致性和重建能力,再决定同步方式、分片、隔离和容量。
思考题
- 为什么搜索系统常用 CQRS 或投影架构?
- 双写 MySQL 和 ES 有什么风险?
- Kafka 在 ES 数据链路中解决哪些问题?
- 多租户应如何组合索引隔离和 DLS?
- 哪些分析应该迁移到数仓而不是继续放大 ES 集群?