背景:当 Elasticsearch 集群数据量达到 2 亿文档、日请求量 300 万+,前端查询页面出现 白屏(即无响应或超时)
在 Elasticsearch(ES)中实现 读写分离,并不是像传统数据库那样通过主从复制自动分流读写请求,而是通过 架构设计 + 节点角色划分 + 客户端路由策略 来实现:
写入流量 → 专用 Ingest 节点(或协调节点) → 数据节点
查询流量 → 专用 Coordinating 节点 → 数据节点
这样可以避免高并发写入影响查询性能,提升系统稳定性和响应速度。
一、核心概念说明
节点类型 角色说明 是否存储数据
Ingest Node 执行预处理(如 grok 解析、字段转换),不参与查询协调 ❌ 否
Coordinating Node(协调节点) 接收客户端请求,分发到数据节点,合并结果返回 ❌ 否
Data Node 存储分片,执行索引和查询操作 ✅ 是
Master Node 管理集群状态、分片分配等(通常独立部署) ❌ 否
✅ 读写分离的本质:
写入路径:Client → Ingest Node → Data Node
查询路径:Client → Dedicated Coordinating Node → Data Node
两者物理隔离,互不影响。
二、具体实施步骤
步骤 1:规划节点角色(以 6 节点集群为例)
节点 IP 角色配置(elasticsearch.yml)
node-1, node-2 192.168.1.101~102 node.roles: [ master ]
node-3, node-4 192.168.1.103~104 node.roles: [ data ]
node-5 192.168.1.105 node.roles: [ ingest ]
node-6 192.168.1.106 node.roles: [ ] ← 纯协调节点(无任何角色)
🔔 注意:
纯协调节点:不设置任何 node.roles,默认就是 coordinating-only。
Ingest 节点:只开启 ingest 角色,避免承担查询协调压力。
步骤 2:配置 elasticsearch.yml(关键)
▶ 写入专用节点(Ingest Node)
yaml
编辑
# node-5: ingest node
cluster.name: my-es-cluster
node.name: ingest-node-1
node.roles: [ ingest ] # 仅做预处理
network.host: 0.0.0.0
discovery.seed_hosts: ["192.168.1.101", "192.168.1.102"]
cluster.initial_master_nodes: ["node-1", "node-2"]
▶ 查询专用节点(Coordinating Node)
yaml
编辑
# node-6: coordinating-only node
cluster.name: my-es-cluster
node.name: coord-node-1
# 不设置 node.roles → 默认为 coordinating-only
network.host: 0.0.0.0
discovery.seed_hosts: ["192.168.1.101", "192.168.1.102"]
cluster.initial_master_nodes: ["node-1", "node-2"]
▶ 数据节点(Data Node)
yaml
编辑
# node-3, node-4
node.roles: [ data ]
# 可选:关闭 ingest 和 coordinating 功能(非必须)
✅ 重启所有节点使配置生效。
步骤 3:客户端请求路由(关键!)
▶ 写入请求 → 发往 Ingest 节点
bash
编辑
# 示例:写入文档,经过 pipeline 预处理
curl -X POST "http://192.168.1.105:9200/my-index/_doc?pipeline=my-pipeline" \
-H "Content-Type: application/json" \
-d '{ "log": "2025-04-05 INFO user login" }'
客户端 SDK 或 Logstash 配置 ingest 节点地址 作为写入 endpoint。
▶ 查询请求 → 发往 Coordinating 节点
bash
编辑
# 示例:搜索请求
curl -X GET "http://192.168.1.106:9200/my-index/_search" \
-H "Content-Type: application/json" \
-d '{ "query": { "match": { "message": "login" } } }'
前端/后端服务配置 coordinating 节点地址 作为查询 endpoint。
💡 最佳实践:
使用 负载均衡器(如 Nginx、HAProxy) 分别代理两类请求:
write.es.example.com → 指向 ingest 节点池
read.es.example.com → 指向 coordinating 节点池
步骤 4:配置 Ingest Pipeline(可选但推荐)
创建预处理管道,减轻应用层负担:
json
编辑
PUT _ingest/pipeline/user-login-pipeline
{
"description": "Parse login log",
"processors": [
{
"grok": {
"field": "log",
"patterns": ["%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{DATA:message}"]
}
},
{
"date": {
"field": "timestamp",
"formats": ["yyyy-MM-dd HH:mm:ss"]
}
}
]
}
写入时指定 pipeline:
json
编辑
POST /logs/_doc?pipeline=user-login-pipeline
{ "log": "2025-04-05 10:00:00 INFO user login" }
三、优势与注意事项
✅ 优势
方面 说明
性能隔离 写入的 CPU/内存开销(如 grok 解析)不影响查询延迟
稳定性提升 查询高峰不会阻塞写入队列(反之亦然)
弹性扩展 可单独扩容 ingest 或 coordinating 节点
可观测性 监控指标按角色分离,问题定位更快
⚠️ 注意事项
不要让数据节点同时承担协调任务
→ 在数据节点上显式设置 node.roles: [ data ],避免默认开启 coordinating。
协调节点也需要足够内存
→ 聚合查询需在协调节点合并结果,建议 16GB+ 内存。
Ingest 节点不是必须的
→ 如果写入前已在应用层完成清洗(如 Logstash),可直接写入数据节点,此时“写入路径”可走另一组 coordinating 节点。
监控线程池
关注 ingest 节点的 ingest 线程池
关注 coordinating 节点的 search 线程池
bash
编辑
GET _nodes/stats/thread_pool?pretty
四、架构图示意
编辑
+------------------+
| Application |
+--------+---------+
|
+---------------+-----------------+
| |
+--------v--------+ +---------v---------+
| Write Client | | Read Client |
| (Logstash, App) | | (Web Frontend) |
+--------+--------+ +---------+---------+
| |
| POST /_doc?pipeline=... | GET /_search
v v
+--------+--------+ +---------+---------+
| Ingest Node(s) | | Coordinating Node(s)|
| (Preprocessing) | | (Query Coordination)|
+--------+--------+ +---------+---------+
| |
+---------------+-----------------+
|
+-------v-------+
| Data Node(s) |
| (Shards Store)|
+---------------+
写入流程(以 Ingest 节点为例)

查询流程(以 Coordinating 节点为例)

五、适用场景
日志分析系统:大量写入(Filebeat → Ingest) + 复杂查询(Kibana → Coordinating)
电商商品搜索:商品同步走 ingest pipeline,用户搜索走 dedicated query nodes
高并发业务系统:写入 QPS > 1万,查询 P99 延迟要求 < 500ms
总结
Elasticsearch 的读写分离 = 角色分离 + 请求路由分离:
部署专用 Ingest 节点处理写入预处理;
部署纯 Coordinating 节点处理查询协调;
客户端/网关按用途路由请求;
数据节点专注存储与计算。
这种架构能有效应对你提到的 2亿数据 + 300万日请求 场景,显著降低白屏率,提升系统 SLA。