Elasticsearch集群架构生产最佳实践:从节点角色到容量规划
一、Elasticsearch节点角色配置最佳实践
1.1 节点角色概念的演进
在Elasticsearch 7.9版本之前,配置节点类型时需要繁琐地说明"我不是XXX节点",例如:
node.master: true
node.data: false
node.ingest: false
这种配置方式非常烦琐,逻辑类似于"若我要说明自己是主节点,则要先说明我不是数据节点、不是ingest节点、不是XXX节点......"。
节点角色的革命性改进: Elasticsearch 7.9版本开始引入节点角色的概念,利用节点角色,我们只需要说明"我是XXX"即可,而不需要解释"我不是XXX"。
以Elasticsearch 8.X版本集群为例,如果不手动设置节点角色,默认节点角色为cdfhilmrstw,解释如下:
| 角色 | 说明 |
|---|---|
| c | Coordinator Node (协调节点) |
| d | Data Node (数据节点) |
| f | Ingest Node (预处理节点) |
| h | Master Node (主节点) |
| i | Ingest Node (预处理节点) |
| l | Machine Learning Node (机器学习节点) |
| m | Master Node (主节点) |
| r | Remote Cluster Node (远程集群节点) |
| s | Search Node (搜索节点) |
| t | Transform Node (转换节点) |
| w | Warm Node (温节点) |
重要提示:在集群规模较大后(如节点数大于6个),需要手动设定、配置节点角色。
1.2 生产环境节点角色配置
生产环境建议:
- 为每个节点配置单一角色,避免角色混用
- 不同角色节点使用不同硬件配置
各角色节点配置建议:
| 节点角色 | 配置建议 | 说明 |
|---|---|---|
| 主节点 (Master) | 低配置CPU/RAM/磁盘 | 负责集群状态管理 |
| 数据节点 (Data) | 高配置CPU/RAM/磁盘 | 负责数据存储及处理 |
| Ingest节点 | 高配置CPU/中等RAM/低磁盘 | 负责数据预处理 |
| 协调节点 (Coordinating Only) | 高配置CPU/高配置RAM/低磁盘 | 作为负载均衡器,降低Master和Data Nodes负载 |
配置示例:
# 主节点配置
node.master: true
node.data: false
node.ingest: false
node.roles: ["master"]
# 数据节点配置
node.master: false
node.data: true
node.ingest: false
node.roles: ["data"]
# 协调节点配置
node.master: false
node.data: false
node.ingest: false
node.roles: ["coordinating"]
1.3 为什么需要单一角色节点
单一角色职责分离的好处:
- 提高系统稳定性:避免节点角色冲突导致的集群不稳定
- 优化资源利用:根据角色需求配置硬件,避免资源浪费
- 易于维护:角色明确,便于故障排查和性能调优
生产环境中,建议为一些大的集群配置Coordinating Only Nodes:
- 作为负载均衡器,降低Master和Data Nodes的负载
- 负责搜索结果的Gather/Reduce
- 有时无法预知客户端会发送怎样的请求(如大量占用内存的操作),使用独立的协调节点可以避免影响主节点和数据节点
二、高可用场景部署方案详解
2.1 读写分离架构
业务场景:
- 每日增量6TB日志数据
- 高峰时段写入及查询频率都较高
- 集群压力较大,查询ES时经常出现查询缓慢问题
解决方案:
- 将集群划分为两类数据节点,不同硬件配置
- Hot Nodes:用于数据的写入
- Warm Nodes:用于保存只读的索引,较旧的数据
硬件配置建议:
- Hot Nodes:使用SSD磁盘,高性能
- Warm Nodes:使用HDD磁盘,大容量
实现方式:
# 标记Hot节点
node.attr.hot: true
# 标记Warm节点
node.attr.warm: true
索引分配到节点:
# 创建索引到Hot节点
PUT index-2022-05
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0,
"index.routing.allocation.require.hot": "true"
}
}
# 创建索引到Warm节点
PUT index-2022-05/_settings
{
"index.routing.allocation.require.warm": "true"
}
2.2 Hot & Warm架构详解
ES为什么要设计Hot & Warm架构?
- ES数据通常不会有Update操作:适用于Time based索引数据
- 适用于数据量比较大的场景:如日志、指标等
- 提升查询效率:使用SSD存储热数据,提升查询效率
- 成本优化:全部使用SSD成本过高,且存放冷数据浪费,使用普通SATA磁盘与SSD混搭,实现资源充分利用
Hot & Warm架构实现步骤:
-
标记节点:
# 标记Hot节点 node.attr.hot: true # 标记Warm节点 node.attr.warm: true -
配置索引到Hot节点:
PUT index-2022-05 { "settings": { "number_of_shards": 2, "number_of_replicas": 0, "index.routing.allocation.require.hot": "true" } } -
配置索引到Warm节点:
PUT index-2022-05/_settings { "index.routing.allocation.require.warm": "true" }
Hot & Warm架构优势:
- 硬件隔离:让客户关注的实时数据和历史数据硬件隔离
- 最大化响应速度:提升热数据查询性能
- 降低成本:使用不同档次的磁盘,降低整体成本
2.3 数据迁移策略
数据迁移步骤:
- 标记节点:通过
node.attr标记节点 - 配置Hot数据:创建索引时指定创建在Hot节点上
- 配置Warm数据:将旧数据移动到Warm节点
数据迁移示例:
# 创建索引到Hot节点
PUT index-2022-05
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0,
"index.routing.allocation.require.hot": "true"
}
}
# 将索引移动到Warm节点
PUT index-2022-05/_settings
{
"index.routing.allocation.require.warm": "true"
}
三、ES跨集群搜索(CCS)实战
3.1 ES跨集群搜索背景
单集群水平扩展存在的问题:
- 节点数不能无限增加
- 当集群的meta信息(节点、索引、集群状态)过多会导致更新压力变大
- 单个Active Master会成为性能瓶颈
早期解决方案:
- Tribe Node:以Client Node方式加入每个集群,但存在以下问题
- 需要Tribe Node回应才能继续
- 不保存Cluster State信息,重启初始化慢
- 多个集群索引重名时,只能设置一种Prefer规则
ES 5.3引入的解决方案:
- 跨集群搜索(Cross Cluster Search, CCS)
- 推荐使用,替代Tribe Node
3.2 CCS配置详解
CCS配置参数:
| 配置项 | 说明 | 默认值 |
|---|---|---|
| seeds | 远程集群的remote cluster的一个node | - |
| connected | 至少有一个到远程集群的连接则为true | - |
| num_nodes_connected | 远程集群中连接节点的数量 | - |
| max_connections_per_cluster | 远程集群维护的最大连接数 | 3 |
| transport.ping_schedule | TCP层面的活性监听 | 30s |
| skip_unavailable | 设置为true时,远程集群不可用则忽略 | false |
| cluster.remote.connections_per_cluster | gateway nodes数量 | 3 |
| cluster.remote.initial_connect_timeout | 节点启动时等待远程节点的超时 | 30s |
| cluster.remote.node.attr | 用于过滤remote cluster中符合gateway nodes的节点 | - |
| cluster.remote.connect | 是否允许节点连接到remote cluster | true |
CCS配置示例:
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster0": {
"seeds": ["127.0.0.1:9300"],
"transport.ping_schedule": "30s"
},
"cluster1": {
"seeds": ["127.0.0.1:9301"],
"transport.compression": true,
"skip_unavailable": true
},
"cluster2": {
"seeds": ["127.0.0.1:9302"]
}
}
}
}
}
3.3 CCS实战案例
搭建3个集群:
# cluster0
elasticsearch.bat -E node.name=cluster0 -E cluster.name=cluster0 -E path.data=cluster0_data -E discovery.type=single-node -E http.port=9200 -E transport.port=9300
# cluster1
elasticsearch.bat -E node.name=cluster1 -E cluster.name=cluster1 -E path.data=cluster1_data -E discovery.type=single-node -E http.port=9201 -E transport.port=9301
# cluster2
elasticsearch.bat -E node.name=cluster2 -E cluster.name=cluster2 -E path.data=cluster2_data -E discovery.type=single-node -E http.port=9202 -E transport.port=9302
创建测试数据:
# cluster0
POST users/_doc
{
"name": "fox",
"age": "30"
}
# cluster1
POST users/_doc
{
"name": "monkey",
"age": "33"
}
# cluster2
POST users/_doc
{
"name": "mark",
"age": "35"
}
执行跨集群搜索:
GET users,cluster1:users,cluster2:users/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 40
}
}
}
}
CCS优势:
- 不需要以Client Node形式加入其他集群
- 以轻量方式,将搜索请求进行代理
- 无需维护Tribe Node的复杂配置
四、集群容量规划与分片设计
4.1 容量规划关键因素
做容量规划前需评估:
-
业务性能需求:
- 文档的总数据量
- 索引的总数据量(Time base数据保留时间)
- 副本分片数
- 文档写入方式(Bulk大小)
- 文档复杂度
- 查询和聚合方式
-
硬件配置:
- 单条文档大小
- 数据吞吐及性能需求
- 数据写入吞吐量(每秒写入数据量)
- 查询吞吐量
- 单条查询可接受的最大返回时间
硬件配置建议:
- 搜索类:按1:16比例配置内存和硬盘
- 日志类:按1:50比例配置内存和硬盘
- 单节点数据建议控制在2TB以内,最大不超过5TB
- JVM配置:机器内存的一半,JVM内存不建议超过32GB
- 不建议在一台服务器上运行多个节点
4.2 容量规划案例
4.2.1 固定大小数据集场景
业务场景:
- 产品信息库
- 搜索特性:关注搜索和聚合的读取性能
- 数据重要性与时间范围无关
- 关注搜索的相关度
容量规划:
- 单个分片数据不要超过20GB
- 通过增加副本分片,提高查询吞吐量
- 如果业务上有大量查询基于某个字段进行Filter,可以考虑以该字段进行索引拆分
案例计算:
- 总数据量1TB,设置一个副本就是2TB
- 搜索类项目,每个节点31GB * 16 = 496GB
- 每个节点最多400GB数据,至少需要5个数据节点
4.2.2 基于时间序列的数据场景
业务场景:
- 日志/指标/安全相关事件
- 每条数据都有时间戳,文档基本不会被更新
- 用户更多查询近期数据,对旧数据查询相对较少
- 对数据写入性能要求高
容量规划:
- 创建基于时间序列的索引
- 按照每天/每周/每月方式划分索引
- 利用Hot & Warm架构
- 基于Index Alias管理最新数据
索引命名示例:
# 按天创建索引
PUT <logs-{now/d}>
索引别名管理:
POST _aliases
{
"actions": [
{
"add": {
"index": "logs_2022-05-27",
"alias": "logs_write"
}
},
{
"remove": {
"index": "logs_2022-05-26",
"alias": "logs_write"
}
}
]
}
4.3 分片设计与管理
分片是ES实现集群水平扩展的最小单位。
分片过多的副作用:
- 从存储角度看:过多分片会导致额外的性能开销
- Lucene Indices/ File descriptors/ RAM/ CPU
- 每次搜索请求需要从每个分片获取数据
- 分片Meta信息由Master节点维护,过多会增加管理负担
经验值:控制分片总数在10W以内
如何确定主分片数:
- 搜索类应用:单个分片不超过20GB
- 日志类应用:单个分片不超过50GB
如何确定副本分片数:
- 提高系统可用性:防止数据丢失
- 增加副本数可以提高服务的可用性
- 但会占用和主分片一样的资源
- 会降低数据的索引速度
- 会消耗同样的内存资源
副本分片数设置建议:
- 业务数据重要性高:设置2-3个副本
- 业务数据重要性一般:设置1个副本
- 业务数据重要性低:不设置副本
分片分配优化:
- 避免分片分布不均
- 提前监控磁盘空间,提前清理数据或增加节点
- 通过
index.routing.allocation.total_shards_per_node控制每个节点的分片数
配置示例:
# 5个节点的集群,索引有5个主分片,1个副本
PUT /my_index/_settings
{
"transient": {
"index.routing.allocation.total_shards_per_node": 2
}
}
五、总结与最佳实践建议
5.1 高可用集群架构总结
| 特性 | 说明 | 实现方式 |
|---|---|---|
| 高可用性 | 服务不中断 | 副本分片+节点故障自动转移 |
| 数据可用性 | 数据不丢失 | 主分片+副本分片机制 |
| 可扩展性 | 应对数据增长 | 添加节点+分片自动重新分配 |
| 安全性 | 数据安全 | ES 8.x默认开启安全认证 |
5.2 最佳实践建议
-
节点角色配置:
- 生产环境使用单一角色节点
- 根据角色需求配置硬件资源
- 避免角色混用
-
高可用部署:
- 对于大数据量场景,采用Hot & Warm架构
- 热数据使用SSD,冷数据使用HDD
- 通过索引属性和路由规则实现数据自动迁移
-
集群扩展:
- 单节点数据控制在2TB以内
- 按1:16比例配置搜索类数据
- 按1:50比例配置日志类数据
- 预留20%的容量余量
-
分片管理:
- 搜索类:单个分片不超过20GB
- 日志类:单个分片不超过50GB
- 控制分片总数在10W以内
- 合理设置副本数,平衡性能和成本
-
安全配置:
- 生产环境必须开启安全认证
- 定期轮换密码
- 限制ES对外端口访问
5.3 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 集群状态为Yellow | 副本分片未分配 | 检查节点状态,确保节点正常运行 |
| 集群状态为Red | 主分片未分配 | 检查磁盘空间,确保磁盘使用率<85% |
| 查询性能差 | 分片过大 | 适当增加分片数,控制单个分片大小 |
| 索引写入慢 | 副本分片过多 | 适当减少副本分片数,平衡性能和可用性 |
| 节点无法加入集群 | 集群名称不一致 | 确保所有节点cluster.name一致 |
结语
Elasticsearch集群架构设计是构建高性能、高可用搜索系统的关键。通过合理配置节点角色、采用Hot & Warm架构、实施跨集群搜索、进行科学的容量规划和分片设计,可以构建出满足业务需求的稳定可靠的ES集群。
在实际生产环境中,ES集群架构并非一成不变,需要根据业务发展和数据增长进行持续优化。希望本文提供的最佳实践能帮助您在ES集群架构设计和优化中少走弯路,提高开发效率和系统稳定性。
小贴士:在生产环境部署ES集群前,务必在测试环境充分验证配置,特别是分片大小、节点角色和安全配置。一个配置错误的ES集群可能带来严重的性能问题和安全风险。
更多推荐
所有评论(0)