高可用架构
一、节点类型
1.1 主节点
协调集群内管理任务,比如索引创建、删除、集群状态更新等
1.2 数据节点
存储实际数据,并执行相关的CRUD操作和搜索请求
1.3 协调节点
接收客户端请求,将请求分发到数据节点并汇总结果,不存储数据
1.4 负载节点
在数据被索引之前,对数据进行预处理,比如解析、变换等
二、高可用
- ElasticSearch通过分片(Shard)机制来实现数据的水平扩展。每个索引可以被分成多个分片,每个分片是一个完整的搜索引擎,可以被分布在集群的多个节点上。为了提高数据的可用性和容错性,每个分片可以有零个或多个副本分片, 分片大于1即可满足基础高可用
- ElasticSearch集群的高可用性是通过多个节点和分片副本来实现的。当一个节点发生故障时,集群能够自动将请求重定向到其他节点,并且可以自动将故障节点上的分片重新分配到其他节点上。
- ElasticSearch使用Zen Discovery模块来进行节点发现和主节点选举。当集群启动或者主节点故障时,会进行一个新的主节点选举过程。这个过程确保了集群始终有一个主节点来管理集群状态。
三、故障转移
当数据节点发生故障时,副本分片会接管请求,并且集群会自动将新的分片分配到其他健康的节点上。这个过程是自动的,无需人工干预。
四、数据一致性
在分布式系统中,数据一致性是一个挑战。ElasticSearch通过以下机制来确保数据的一致性:
4.1 乐观并发控制
ElasticSearch使用乐观并发控制(Optimistic Concurrency Control, OCC)来处理文档版本的冲突。每个文档都有一个版本号,当文档被更新时,版本号会增加。如果两个并发的更新尝试发生冲突,ElasticSearch会拒绝旧版本的更新。
4.2 刷新与提交
ElasticSearch的索引数据不是立即写入磁盘的,而是先存储在内存中,通过定期的刷新(Refresh)操作写入磁盘。这确保了数据的快速响应,但也意味着在刷新间隔内的数据可能会在故障时丢失。为了减少这种风险,可以调整刷新间隔或使用副本分片来提供数据冗余。
五、分片
一个index创建出来, 根据不同es版本有默认(主)分片数量, 7.0之前默认为5 , 7.x及之后默认为1
而且还会默认创建副本分片数量为1
比如一个index在7.6版本创建, 那么它默认一共会产生1个主分配 + 1个副本分片
常见运维场景问题
一、分片与集群设计
如何计算主分片数?副本数设置依据是什么?
主分片数:
- 计算公式:
max( min(节点数 × 1.5, 数据总量/50GB ), 3 ) - 示例:3节点+300GB数据 →
min(4.5, 6) ≈ 5分片 - 硬规则:创建后不可修改,需预留20%增长空间
- 计算公式:
副本数:
- 基础容灾:≥1(允许宕机1节点)
- 读性能提升:每增加1副本,读吞吐提升30-50%
- 特殊场景:
- 单节点集群:必须设为0(副本无法分配)
- 跨AZ部署:副本数≥AZ数量-1
二、写入性能优化
如何提升Elasticsearch的写入吞吐量?
2.1 Bulk 调优
- 单批次大小:10-15MB(过大引发GC,过小降低吞吐)
- 并发线程数:
CPU核数×2(观察bulk_rejected调整)
2.2 Refresh 策略
PUT /logs/_settings
{"refresh_interval": "30s"} // 写入期关闭刷新,完成后恢复1s
2.3 Translog 优化
"index.translog.durability": "async" // 异步写入,风险:宕机丢失5s数据
"index.translog.sync_interval": "5s"
2.4 硬件级加速
- 使用 SSD + 分离 data 和 logs 磁盘路径
- 关闭交换分区:sudo swapoff -a
三、常见排障
3.1 yellow
# 1. 检查未分配分片原因:
GET _cluster/allocation/explain?pretty
# 2. 查看磁盘水位(>85%将停止分配):
GET _cat/allocation?v&h=node,disk.percent,shards
# 3. 检查节点负载:
GET _nodes/stats/os,process?filter_path=**.load_5m,**.cpu.percent
# 4. 分析分片锁冲突:
GET _cluster/state?filter_path=metadata.indices.*.state,*.blocks
常见根因:
- 磁盘不足 → 清理或扩容
- 节点配置不一致 → cluster.routing.allocation.enable: all
- 分片损坏 → 使用 reroute 强制分配
3.2 JVM调优
Old GC持续超过5秒,如何优化?
堆内存设置
- 不超过物理内存50%
- 不超过32GB(压缩指针失效阈值)
- 示例:64GB内存 →
-Xms31g -Xmx31g
GC策略
-XX:+UseG1GC
-XX:G1ReservePercent=25 # 预留内存防Evacuation Failure
-XX:InitiatingHeapOccupancyPercent=35 # 提前触发GC
- 堆外内存泄漏排查
# 关注 count 和 used_in_bytes 持续增长
GET _nodes/stats/jvm?filter_path=**.buffer_pools.direct.*
3.3 如何防止未授权访问?
- 网络层 通过配置文件network.host绑定内网ip
- 传输加密 通过开启xpack + 自签证书 bin目录下的keysotre二进制创建带密码的公私钥
- 认证 开启basic认证, es的bin目录下有个elasticsearch-reset-password二进制
四、高可用设计
单机房高可用模式
3master 3client + 多data
日志分等级, 通过template设置主/副分片数量, 通过ilm控制生命周期,
日志通过logstash配置Datastream类型写入提前配置好template的数据流
data通过node.role分冷热节点
用到的节点角色:
master
ingest 数据预处理节点
data_hot
data_warm
data_cold
client设置为空即可作为业务入口
五、版本升级(生产环境)
5.1 如何零停机升级ES 7.x到8.x
前置检查:
- 使用
ES 8 Upgrade Assistant插件扫描 - 解决:type冲突、废弃API、证书兼容
- 使用
滚动升级步骤:
# 1. 停用分片分配(防恢复风暴)
PUT _cluster/settings
{"persistent": {"cluster.routing.allocation.enable": "none"}}
# 2. 逐节点升级:停机 → 装新版本 → 启动 → 重新加入集群
# 3. 开启分片分配并等待绿色
六、描述您解决过的重大ES故障
集群Red
收到集群Red告警,Kibana大量报错,部分日志索引不可用
6.1 初步诊断
# 确认集群状态
GET _cluster/health?pretty → status:red # 40个分片未分配
# 定位异常节点
GET _cat/nodes?v → node-5磁盘使用率98.7%(超过85%默认水位线)
6.2 止血操作
- 扩容磁盘:临时挂载云盘并迁移部分分片
- 通过reroute强制分片分配
- 降级写入:临时关闭非关键日志写入
6.3 根因分析
直接原因:某业务团队误触发全量历史数据重导
深层问题:
* 未设置索引分片上限 → 单节点分片数达120(超最佳实践2倍)
* 缺乏自动处理机制 → 水位超85%未自动清理旧索引
6.4 长期改进
// 通过low和high的合理区间, 加长yellow时间段, 留出足够的时间操作
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": "80%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.max_shards_per_node": 500 // 限制全局分片总数
}
}
配置示例
ELK日志节点
cluster.name: ohmy-log
network.host: 0.0.0.0
http.port: 9200
node.name: es-hotdata-132
node.roles: [ data, ingest ]
node.attr.box_type: hot
path.data: /app/data/elasticsearch
path.logs: /var/log/elasticsearch
bootstrap.memory_lock: true
# 所有master ip
discovery.seed_hosts: ["192.168.11.100","192.168.11.101","192.168.11.102"]
xpack.monitoring.templates.enabled: true
xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl:
enabled: false
# 需要预先生成证书
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: elastic-certificates.p12
truststore.path: elastic-certificates.p12
业务节点
cluster.name: ohmy-es8
node.name: "bookinfo-1"
node.attr.box_type: bookinfo
node.attr.node_type: VM
node.attr.zone: ohmy-home
path.data: "/app/data/elasticsearch"
path.logs: "/var/log/elasticsearch"
network.host: 0.0.0.0
discovery.seed_hosts: ["192.168.33.1","192.168.33.2","192.168.33.3"]
转载请注明来源, 欢迎对文章中的引用来源进行考证, 欢迎指出任何有错误或不够清晰的表达, 可以邮件至 chinaops666@gmail.com