一、先看看集群是不是真的"生病了"
当Elasticsearch集群闹脾气的时候,第一步就是要确认它到底哪里不舒服。就像人生病要先量体温一样,我们可以用最简单的API来检查集群的健康状况:
# 使用curl命令检查集群健康状态(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cluster/health?pretty'
# 返回结果示例:
{
"cluster_name" : "my-cluster",
"status" : "yellow", # 这里就是健康状态:green(健康)、yellow(警告)、red(危险)
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 2,
"active_primary_shards" : 15,
"active_shards" : 30,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 5, # 这是个危险信号!
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 85.71428571428571
}
看到这个结果,我们重点关注三个地方:
- status字段:这是集群的总体健康状态
- unassigned_shards:未分配的分片数量
- active_shards_percent_as_number:活跃分片百分比
二、常见的"病症"表现和诊断方法
2.1 分片分配问题
分片分配失败是最常见的"病症"之一。就像快递员送不了快递一样,分片无法分配到节点上。我们可以深入检查未分配的分片:
# 查看未分配分片的详细信息(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cat/shards?v' | grep UNASSIGNED
# 返回示例:
index-2023.01.01 3 p UNASSIGNED # 索引名称 分片编号 主分片(p) 状态
index-2023.01.01 4 r UNASSIGNED # r表示副本分片
找到问题分片后,我们可以查看具体原因:
# 查看分片未分配的原因(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cluster/allocation/explain?pretty'
# 返回结果会详细说明为什么分片无法分配,比如:
# 1. 磁盘空间不足
# 2. 节点不符合分配规则
# 3. 分片数据损坏
2.2 节点离线问题
有时候集群状态异常是因为某些节点掉线了。我们可以检查节点状态:
# 查看节点状态(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cat/nodes?v'
# 返回示例:
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.1.1 45 95 25 2.50 1.80 1.20 di - node-1
192.168.1.2 80 99 90 15.00 12.00 10.00 di * node-2
192.168.1.3 - - - - - - - - (离线)
2.3 索引级别的问题
有时候问题出在特定索引上,我们可以检查索引状态:
# 查看所有索引状态(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cat/indices?v'
# 返回示例:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open my-index-2023.01 abc123... 5 1 100000 5000 5.2gb 2.6gb
red open problem-index xyz789... 3 1 0 0 230b 115b
三、对症下药:常见问题的解决方案
3.1 解决未分配分片问题
根据前面诊断出的原因,我们可以采取不同措施:
# 如果是磁盘空间不足导致的,可以尝试调整磁盘水位线(技术栈:Elasticsearch 7.x)
curl -XPUT 'http://localhost:9200/_cluster/settings' -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": "85%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.routing.allocation.disk.watermark.flood_stage": "95%"
}
}'
# 如果是分配规则问题,可以临时禁用分配规则检查
curl -XPUT 'http://localhost:9200/_cluster/settings' -H 'Content-Type: application/json' -d'
{
"transient": {
"cluster.routing.allocation.enable": "all"
}
}'
# 手动重新路由分片(谨慎使用!)
curl -XPOST 'http://localhost:9200/_cluster/reroute?retry_failed=true' -H 'Content-Type: application/json' -d'
{
"commands": [
{
"allocate_stale_primary": {
"index": "problem-index",
"shard": 0,
"node": "node-1",
"accept_data_loss": true
}
}
]
}'
3.2 处理节点离线问题
当节点离线时,我们需要判断是临时故障还是永久故障:
# 如果是临时故障,可以等待节点恢复
# 如果是永久故障,需要将节点从集群中移除
# 查看集群配置中是否有错误的节点配置(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_nodes/settings?pretty'
# 如果确认节点永久离线,可以更新集群配置
# 1. 修改elasticsearch.yml文件,移除故障节点
# 2. 重启集群中的其他节点
3.3 修复损坏的索引
对于损坏的索引,我们可以尝试以下方法:
# 首先尝试关闭再打开索引(技术栈:Elasticsearch 7.x)
curl -XPOST 'http://localhost:9200/problem-index/_close'
curl -XPOST 'http://localhost:9200/problem-index/_open'
# 如果无效,可以尝试从副本恢复
curl -XPOST 'http://localhost:9200/problem-index/_recovery?pretty'
# 最坏情况下,可能需要重建索引
curl -XPOST 'http://localhost:9200/_reindex' -H 'Content-Type: application/json' -d'
{
"source": {
"index": "problem-index"
},
"dest": {
"index": "problem-index-new"
}
}'
四、预防胜于治疗:集群健康监控与维护
4.1 设置合理的监控告警
我们可以使用Elasticsearch自带的监控功能:
# 设置集群健康监控(技术栈:Elasticsearch 7.x)
curl -XPUT 'http://localhost:9200/_watcher/watch/cluster_health_watch' -H 'Content-Type: application/json' -d'
{
"trigger": {
"schedule": {
"interval": "10m"
}
},
"input": {
"http": {
"request": {
"host": "localhost",
"port": 9200,
"path": "/_cluster/health"
}
}
},
"condition": {
"compare": {
"ctx.payload.status": {
"not_eq": "green"
}
}
},
"actions": {
"send_email": {
"email": {
"to": "admin@example.com",
"subject": "集群健康状态警告",
"body": "集群状态: {{ctx.payload.status}}"
}
}
}
}'
4.2 定期维护操作
# 定期清理旧索引(技术栈:Elasticsearch 7.x)
# 使用Curator工具可以方便地管理索引生命周期
curator --config config.yml action.yml
# config.yml内容:
client:
hosts:
- localhost
port: 9200
url_prefix:
use_ssl: False
certificate:
client_cert:
client_key:
aws_key:
aws_secret_key:
aws_region:
ssl_no_validate: False
http_auth:
timeout: 30
master_only: False
# action.yml内容:
actions:
1:
action: delete_indices
description: "删除30天前的索引"
options:
ignore_empty_list: True
timeout_override:
continue_if_exception: False
disable_action: False
filters:
- filtertype: pattern
kind: prefix
value: "logstash-"
- filtertype: age
source: name
direction: older
timestring: "%Y.%m.%d"
unit: days
unit_count: 30
4.3 容量规划建议
- 每个节点的分片总数建议控制在1000以下
- 单个分片大小建议在10GB-50GB之间
- 预留20%的磁盘空间用于维护操作
- 监控JVM堆内存使用情况,建议不超过32GB
五、高级排查技巧
5.1 使用诊断API
# 获取详细的诊断信息(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_cluster/state?pretty&filter_path=metadata.indices, routing_table.indices'
# 这个API会返回非常详细的集群状态信息,包括:
# 1. 所有索引的元数据
# 2. 分片路由信息
# 3. 索引设置
5.2 检查线程池状态
# 查看线程池状态(技术栈:Elasticsearch 7.x)
curl -XGET 'http://localhost:9200/_nodes/thread_pool?pretty'
# 重点关注rejected值,如果这个数字很大,说明线程池队列已满
# 可能需要调整线程池配置:
curl -XPUT 'http://localhost:9200/_cluster/settings' -H 'Content-Type: application/json' -d'
{
"persistent": {
"thread_pool.search.queue_size": 2000,
"thread_pool.index.queue_size": 500
}
}'
5.3 检查慢查询日志
# 启用慢查询日志(技术栈:Elasticsearch 7.x)
curl -XPUT 'http://localhost:9200/my-index/_settings' -H 'Content-Type: application/json' -d'
{
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.query.trace": "500ms",
"index.search.slowlog.threshold.fetch.warn": "1s",
"index.search.slowlog.threshold.fetch.info": "800ms",
"index.search.slowlog.threshold.fetch.debug": "500ms",
"index.search.slowlog.threshold.fetch.trace": "200ms",
"index.search.slowlog.level": "info"
}'
# 查看慢查询日志
curl -XGET 'http://localhost:9200/_nodes/stats/indices/search?pretty'
六、总结与最佳实践
经过上面的排查和处理,相信大部分集群健康问题都能得到解决。下面总结一些最佳实践:
- 监控先行:建立完善的监控体系,在问题发生前就能发现征兆
- 容量规划:合理规划集群规模,避免资源不足导致的问题
- 定期维护:建立索引生命周期管理策略,定期清理旧数据
- 配置优化:根据业务特点调整Elasticsearch的各种参数
- 文档记录:记录每次故障的处理过程,形成知识库
记住,处理Elasticsearch集群问题就像医生看病一样,需要先诊断再治疗。盲目操作可能会让问题变得更糟。希望这篇文章能帮助你成为Elasticsearch集群的"良医"!
评论