MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

ElasticSearch集群indexrecovery的故障排查

2022-12-061.4k 阅读

ElasticSearch 集群 index recovery 的故障排查

理解 index recovery

在 ElasticSearch 集群中,index recovery 是一个关键过程,当索引分片需要重建、恢复或重新分配时就会发生。例如,当节点故障、新节点加入集群、或者由于配置更改导致分片重新平衡时,都会触发 index recovery。这个过程涉及到从副本分片复制数据,或者从持久化存储(如磁盘)加载数据到内存等操作。

ElasticSearch 采用了一种称为“主 - 副本”的架构来确保数据的高可用性和容错性。每个索引由一个或多个主分片以及零个或多个副本分片组成。当发生 index recovery 时,副本分片可以作为源数据来恢复主分片,反之亦然。

常见故障现象

  1. recovery 长时间挂起:在 ElasticSearch 的监控指标中,发现某些分片的 recovery 状态长时间处于“in_progress”,没有任何进展。例如,通过 ElasticSearch 的 REST API /_cluster/health?level=shards 查看集群健康状态时,部分分片的 recovery_status 一直显示为“initializing”或“recovering”。
  2. recovery 失败并报错:ElasticSearch 的日志文件中出现大量与 recovery 相关的错误信息。例如,可能会出现类似“Failed to recover shard [shard_id] on node [node_name]”的错误,错误详情可能涉及网络问题、磁盘空间不足、数据校验失败等。
  3. 集群健康状态异常:由于 index recovery 故障,集群健康状态可能从“green”(所有分片都可用)变为“yellow”(所有主分片可用,但部分副本分片不可用)或“red”(部分主分片不可用)。通过 /_cluster/health API 可以直观地看到集群健康状态的变化。

故障排查步骤

  1. 检查网络连接
    • 节点间连通性:确保 ElasticSearch 集群中的所有节点之间能够相互通信。可以使用 ping 命令初步检查节点之间的网络连通性。例如,在 Linux 系统中,从节点 A 到节点 B 执行 ping node_B_ip。如果 ping 不通,可能是网络配置问题,如防火墙规则阻止了节点间的通信。
    • 端口检查:ElasticSearch 使用多个端口进行节点间通信和对外服务。默认情况下,9300 端口用于节点间通信,9200 端口用于 HTTP 接口。确保这些端口在所有节点上都已开放。在 Linux 系统中,可以使用 netstat -tlnp 命令查看端口是否监听,例如:
netstat -tlnp | grep 9300
netstat -tlnp | grep 9200

如果端口未监听,检查 ElasticSearch 服务是否正常启动,或者是否有其他进程占用了这些端口。

  • 网络延迟和丢包:高网络延迟或频繁丢包也可能导致 index recovery 问题。可以使用 traceroute 命令查看数据包的路由路径,同时使用 mtr 工具持续监控网络延迟和丢包情况。例如,在 Linux 系统中执行 mtr node_B_ip,该命令会实时显示到目标节点的网络延迟和丢包率。如果发现网络延迟过高或丢包严重,需要联系网络管理员排查网络设备(如路由器、交换机)的问题。
  1. 查看磁盘状态
    • 磁盘空间:index recovery 需要足够的磁盘空间来存储数据。使用 df -h 命令查看每个节点的磁盘使用情况。例如:
df -h

如果某个节点的磁盘空间使用率接近 100%,可能会导致 index recovery 失败。可以通过清理不必要的文件、删除旧的日志等方式释放磁盘空间。

  • 磁盘 I/O 性能:低磁盘 I/O 性能也可能影响 index recovery 的速度。可以使用工具如 iostat 来监控磁盘 I/O 情况。在 Linux 系统中,安装 sysstat 包后执行 iostat -x 1,该命令会每秒输出一次磁盘 I/O 统计信息,包括读写速度、等待时间等。如果发现磁盘 I/O 性能低下,可能需要考虑更换磁盘设备或优化磁盘配置(如调整 I/O 调度算法)。
  1. 分析 ElasticSearch 日志
    • 定位 recovery 相关日志:ElasticSearch 的日志文件通常位于安装目录的 logs 子目录下。在日志文件中搜索与 index recovery 相关的关键字,如“recovery”、“shard”等。例如,在 elasticsearch.log 文件中可以使用 grep 命令进行搜索:
grep -i "recovery" elasticsearch.log
  • 常见错误分析
    • 数据校验失败:如果日志中出现“Checksum failed”相关错误,说明在数据复制或传输过程中可能发生了数据损坏。这可能是由于网络问题、磁盘故障等原因导致的。可以尝试重新启动相关节点,或者从其他副本分片重新进行 recovery。
    • 版本不兼容:当 ElasticSearch 集群中节点的版本不一致时,可能会出现 index recovery 问题。日志中可能会有类似“Version conflict”的错误。确保所有节点都使用相同版本的 ElasticSearch。
  1. 检查集群配置
    • 分片和副本配置:检查索引的分片和副本配置是否合理。可以通过 /_cat/indices?v API 查看索引的分片和副本数量。例如:
curl -XGET 'http://localhost:9200/_cat/indices?v'

如果配置的副本数量过多,可能会导致 recovery 压力过大。可以根据实际需求适当调整副本数量。

  • 节点角色配置:确保节点的角色配置正确。ElasticSearch 节点可以有不同的角色,如 masterdataingest 等。如果节点角色配置错误,可能会影响 index recovery。可以在 elasticsearch.yml 配置文件中检查节点角色配置,例如:
node.master: true
node.data: true
node.ingest: true

确保每个节点的角色配置符合集群的设计。 5. 排查资源限制

  • 文件描述符限制:ElasticSearch 需要打开大量的文件描述符来处理索引和数据。在 Linux 系统中,可以通过 ulimit -n 命令查看当前用户的文件描述符限制。如果限制过低,可能会导致 index recovery 问题。可以通过修改 limits.conf 文件来提高文件描述符限制,例如:
echo "elasticsearch soft nofile 65536" | sudo tee -a /etc/security/limits.conf
echo "elasticsearch hard nofile 65536" | sudo tee -a /etc/security/limits.conf

然后重新登录或重启 ElasticSearch 服务使配置生效。

  • 内存限制:index recovery 过程中需要一定的内存来处理数据。确保 ElasticSearch 节点有足够的内存可用。可以通过 free -h 命令查看系统内存使用情况。如果内存不足,可能需要调整 ElasticSearch 的堆内存配置,在 elasticsearch.yml 文件中修改 heap.size 参数,例如:
# 设置堆内存为 4GB
heap.size: 4g

注意,堆内存设置过高可能会导致系统内存不足,需要根据实际情况进行调整。

代码示例:使用 ElasticSearch REST API 监控 recovery

  1. 查看集群健康状态
    • 使用 curl 命令可以很方便地获取 ElasticSearch 集群的健康状态,包括 index recovery 的相关信息。例如,获取详细的集群健康状态(包括分片级别):
curl -XGET 'http://localhost:9200/_cluster/health?level=shards'

返回结果示例:

{
  "cluster_name": "my_cluster",
  "status": "yellow",
  "timed_out": false,
  "number_of_nodes": 3,
  "number_of_data_nodes": 3,
  "active_primary_shards": 5,
  "active_shards": 5,
  "relocating_shards": 0,
  "initializing_shards": 1,
  "unassigned_shards": 1,
  "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": 83.33333333333334,
  "shards": {
    "my_index": {
      "0": {
        "status": "recovering",
        "primary": true,
        "active_shards": 1,
        "relocating_shards": 0,
        "initializing_shards": 1,
        "unassigned_shards": 0
      },
      "1": {
        "status": "active",
        "primary": false,
        "active_shards": 1,
        "relocating_shards": 0,
        "initializing_shards": 0,
        "unassigned_shards": 0
      }
    }
  }
}

从上述结果中,可以看到 my_index 索引的 0 号分片正在进行 recovery(status 为“recovering”)。 2. 查看索引的分片状态

  • 可以使用 /_cat/shards API 查看索引的分片状态,包括 recovery 状态。例如:
curl -XGET 'http://localhost:9200/_cat/shards/my_index?v'

返回结果示例:

index    shard prirep state      docs store ip         node
my_index 0     p      recovering 10   20kb 192.168.1.10 node1
my_index 0     r      initializing 0   0b   192.168.1.11 node2
my_index 1     p      active     15   30kb 192.168.1.12 node3
my_index 1     r      active     15   30kb 192.168.1.10 node1

从结果中可以看到 0 号主分片处于“recovering”状态,对应的副本分片处于“initializing”状态。

深入理解 recovery 机制

  1. recovery 阶段
    • 初始化阶段:当触发 index recovery 时,首先进入初始化阶段。在这个阶段,ElasticSearch 会确定源分片和目标分片,以及需要恢复的数据范围。例如,如果是由于节点故障导致的 recovery,ElasticSearch 会从其他副本分片找到最新的数据版本,并确定需要传输的数据块。
    • 传输阶段:在初始化完成后,进入传输阶段。源分片开始将数据传输到目标分片。这个过程中,数据会通过网络进行复制。ElasticSearch 使用了一种称为“chunk - based”的传输方式,将数据分成多个小块进行传输,以提高传输效率和可靠性。例如,每个数据块可能大小为 1MB,源分片会依次将这些数据块发送给目标分片。
    • 合并阶段:目标分片接收到数据块后,进入合并阶段。在这个阶段,目标分片会将接收到的数据块合并成完整的分片数据。同时,会进行数据校验和元数据更新等操作,确保恢复的数据与源数据一致。
  2. 影响 recovery 速度的因素
    • 网络带宽:网络带宽直接影响数据传输的速度。如果节点间网络带宽较低,数据传输阶段会花费更长的时间,从而延长整个 recovery 过程。例如,在一个 100Mbps 的网络环境中传输 10GB 的数据,相比于 1Gbps 的网络环境,所需时间会明显增加。
    • 磁盘 I/O 性能:在合并阶段,目标分片需要将接收到的数据写入磁盘。如果磁盘 I/O 性能低下,如磁盘读写速度慢,会导致合并阶段的延迟增加。例如,机械硬盘的读写速度通常比固态硬盘慢,使用机械硬盘的节点在 recovery 时可能会比使用固态硬盘的节点花费更多时间。
    • 数据量大小:显然,需要恢复的数据量越大,recovery 所需的时间就越长。如果一个索引有大量的文档和较大的字段值,其 recovery 过程会相对较慢。例如,一个包含数十亿文档的索引的 recovery 时间会远远长于一个只有几千文档的索引。
    • 集群负载:当集群处于高负载状态时,如大量的写入、查询操作正在进行,会影响 index recovery 的资源分配。ElasticSearch 会在各种操作之间分配资源,如果集群负载过高,可能没有足够的资源(如 CPU、内存)用于 index recovery,从而导致 recovery 速度变慢。

高级故障排查技巧

  1. 使用 ElasticSearch 插件
    • Marvel 插件(已集成到 X - Pack):Marvel 插件提供了强大的集群监控和分析功能。通过它可以直观地看到 index recovery 的实时状态、进度以及历史记录。安装 X - Pack 后,可以通过 Kibana 的界面访问 Marvel 的功能。在 Kibana 的“Monitoring”选项卡中,可以查看集群的各项指标,包括 index recovery 的相关指标,如传输速率、剩余时间等。
    • Curator 插件:Curator 插件可以用于管理 ElasticSearch 索引,包括索引的创建、删除、备份等操作。在排查 index recovery 故障时,可以使用 Curator 来清理无效的索引或分片,优化集群状态。例如,可以使用 Curator 删除那些长时间处于“unassigned”状态的分片,避免它们对集群健康状态产生负面影响。安装 Curator 后,可以通过命令行工具进行操作,例如:
# 删除所有状态为“unassigned”的分片
curator delete_unassigned
  1. 深入分析 JVM 日志
    • GC 日志分析:ElasticSearch 是基于 Java 开发的,JVM 的垃圾回收(GC)情况会影响其性能,包括 index recovery。通过分析 GC 日志,可以了解 JVM 的内存使用情况和垃圾回收频率。在 elasticsearch.yml 文件中配置 GC 日志输出:
# 配置 GC 日志路径和格式
logging.gc: true
logging.gc.path: /var/log/elasticsearch/gc.log
logging.gc.rolling: true

然后使用工具如 gceasy.io 上传 GC 日志进行分析。如果发现频繁的 Full GC 或者长时间的 GC 停顿,可能需要调整 JVM 的堆内存大小或 GC 策略,以提高 ElasticSearch 的性能,进而改善 index recovery 情况。

  • 线程转储分析:当 index recovery 出现问题时,可以获取 ElasticSearch 节点的线程转储(thread dump)来分析线程的运行状态。在 Linux 系统中,可以使用 jstack 命令获取线程转储。例如,先通过 ps -ef | grep elasticsearch 找到 ElasticSearch 进程的 PID,然后执行 jstack <pid> > thread_dump.txt。分析线程转储文件,可以查看是否有线程死锁、线程长时间等待等问题,这些问题可能会导致 index recovery 故障。

案例分析

  1. 案例一:网络问题导致 recovery 失败
    • 故障现象:一个包含 5 个节点的 ElasticSearch 集群,其中一个数据节点突然故障重启。重启后,部分索引的分片一直处于“recovering”状态,集群健康状态变为“red”。
    • 排查过程
      • 首先检查网络连接,通过 ping 命令发现故障节点重启后与其他节点之间存在高延迟和丢包现象。
      • 使用 traceroute 命令发现数据包在某一跳路由器处出现异常。联系网络管理员排查,发现该路由器的一个端口出现硬件故障。
    • 解决方案:更换路由器故障端口后,网络恢复正常,index recovery 过程顺利完成,集群健康状态恢复为“green”。
  2. 案例二:磁盘空间不足导致 recovery 失败
    • 故障现象:在一个 ElasticSearch 集群中,新创建了一个较大的索引,随后发现该索引的部分分片无法完成 recovery,集群健康状态变为“yellow”。
    • 排查过程
      • 使用 df -h 命令检查各个节点的磁盘空间,发现其中一个数据节点的磁盘使用率达到了 98%。
      • 进一步分析发现该节点上存储了大量的旧日志文件和临时文件。
    • 解决方案:清理该节点上的旧日志文件和临时文件,释放磁盘空间。重新触发 index recovery,分片成功恢复,集群健康状态恢复为“green”。

预防措施

  1. 定期监控:使用 ElasticSearch 自带的监控 API 或者第三方监控工具(如 Grafana 结合 ElasticSearch 数据源)定期监控集群的健康状态、节点资源使用情况(如 CPU、内存、磁盘空间、网络带宽)以及 index recovery 的相关指标(如正在进行的 recovery 数量、平均 recovery 时间等)。设置合理的告警阈值,当指标超出阈值时及时通知运维人员。
  2. 硬件和网络优化:确保服务器硬件(如磁盘、内存、CPU)性能满足业务需求,定期进行硬件检查和维护。优化网络配置,避免网络瓶颈和不稳定因素。例如,使用高速网络设备、合理设置网络带宽分配等。
  3. 版本管理:保持 ElasticSearch 集群中所有节点的版本一致性。在进行版本升级时,提前做好测试,确保新版本与现有配置和数据兼容。同时,关注 ElasticSearch 的官方发布信息,及时了解版本更新中的 bug 修复和性能优化内容。
  4. 配置优化:根据业务需求合理配置索引的分片和副本数量。避免配置过多的副本导致 recovery 压力过大,同时也要确保有足够的副本以保证数据的高可用性。优化节点角色配置,根据节点的硬件资源和业务场景合理分配 masterdataingest 等角色。

通过以上对 ElasticSearch 集群 index recovery 故障排查的详细介绍,包括常见故障现象、排查步骤、代码示例、深入理解机制、高级技巧、案例分析以及预防措施等方面,希望能帮助读者更好地应对和解决 index recovery 过程中出现的各种问题,保障 ElasticSearch 集群的稳定运行。