跳转到内容

故障模式运维手册:节点、网络、磁盘

凌晨 3 点出故障时,你需要的是一张表,而不是一本教科书。本页就是那张表。它把每一种基础设施故障模式——节点崩溃、网络分区、磁盘问题——映射到对应的数据丢失风险、可用性影响、恢复复杂度以及精确的修复步骤。贯穿全文的有三条规则:少数派故障会自愈,多数派故障需要你介入,而法定人数(quorum)就是二者的分界线。

如果想了解字节级别的内部机制——日志布局、term 文件、录制段(recording segments)——请参阅 The Aeron Files。本页是面向运维人员的手册,而非线格式(wire format)说明。

先从集群本身说起。下面的模式贯穿每一行:丢失少数派,Aeron 会自行恢复;丢失多数派,则必须由你手动恢复法定人数。

情形数据丢失风险可用性影响恢复复杂度修复方案
单个 follower 崩溃无(法定人数保持)低——自动追赶重启节点;通过 snapshot + 从 leader 回放日志自动追赶
单个 leader 崩溃未提交的消息短暂(选举超时)低——自动选举等待自动选举;重启崩溃节点以 follower 身份重新加入;客户端重连到新 leader
多个节点崩溃(少数派)无(已无容错余量)低——自动追赶尽快重启崩溃节点以恢复容错能力;监控法定人数健康状况
多个节点崩溃(多数派 / 法定人数丢失)未提交的消息完全不可用,直至恢复高——需手动介入重启足够多的节点以恢复法定人数;若数据丢失,从最新 snapshot + 日志备份恢复
所有节点同时崩溃可能丢失完全不可用高——snapshot + 日志恢复冷启动所有节点;每个节点从本地 snapshot + 日志录制回放;若损坏,从外部备份恢复
  • 少数派故障会自愈——Aeron 自动处理。
  • 多数派故障需要手动介入——你必须恢复法定人数。
  • “未提交的消息” 仅指 leader 已接受但尚未复制到多数派的消息——通常是一个非常小的时间窗口。

从外部备份恢复(第 4 个节点异步副本)

Section titled “从外部备份恢复(第 4 个节点异步副本)”

当集群使用 Aeron Cluster Backup 将数据异步复制到第 4 个(非投票)节点时,可按以下流程从该外部备份恢复。

  • 第 4 个节点运行 ClusterBackup agent,持续从活跃集群接收 snapshot 和日志段。
  • 备份数据位置通过 ClusterBackup.Context 配置(例如 backupResponseChannelbackupDir)。
  • 备份节点存储:最新 snapshot + 后续日志录制
  1. 停止所有存活的集群节点(如果还有节点在运行),以防止脑裂(split-brain)。

  2. 定位第 4 个节点上的备份数据。

    • 找到备份目录(在 ClusterBackup.Context.backupDir() 中配置)。
    • 验证最新 snapshot 和录制日志文件完好无损:
      Terminal window
      # List snapshot and log recordings in the backup dir
      ls -lah /path/to/backup-dir/
      # Use AeronStat or RecordingLog tool to inspect recording state
      java -cp aeron-all.jar io.aeron.cluster.RecordingLog /path/to/backup-dir/
  3. 将备份数据复制到每个集群节点。

    • 对集群中的每个节点,用备份替换其损坏/丢失的数据:
      Terminal window
      # On each cluster node, clear the old cluster dir
      rm -rf /path/to/node-X/cluster-dir/*
      # Copy snapshot + recording log from the 4th node backup
      scp -r backup-node:/path/to/backup-dir/* /path/to/node-X/cluster-dir/
    • 确保每个节点上的文件归属和权限正确。
  4. 更新集群标记文件(如有需要)。

    • 每个节点的 cluster-mark.dat 必须反映正确的 memberId
    • 如果恢复到相同节点且 member ID 不变,则无需改动。
    • 如果节点身份发生变化,需相应更新集群配置。
  5. 先引导 leader 节点。

    • 选一个节点先启动——它会回放 snapshot + 日志并成为初始 leader。
    • 用以下命令启动:
      Terminal window
      # Start the first node; it will replay snapshot and logs
      java -cp your-app.jar <MainClass> --cluster-dir /path/to/node-0/cluster-dir/
    • 等待它完全回放完毕并进入 LEADER 状态(通过 AeronStat 或应用日志查看)。
  6. 启动其余 follower 节点。

    • 逐个启动其他集群节点。
    • 每个节点都会通过 snapshot 安装 + 日志回放从 leader 追赶:
      Terminal window
      java -cp your-app.jar <MainClass> --cluster-dir /path/to/node-1/cluster-dir/
      java -cp your-app.jar <MainClass> --cluster-dir /path/to/node-2/cluster-dir/
  7. 验证集群健康状况。

    • 确认所有节点已加入且法定人数已建立。
    • 通过 AeronStat 检查共识模块(consensus module)的计数器:
      Terminal window
      java -cp aeron-all.jar io.aeron.driver.status.AeronStat
    • 验证 LEADERFOLLOWER 角色分配正确。
    • 运行应用级合理性检查(例如查询状态、检查序列号)。
  8. 重启第 4 个备份节点。

    • 集群恢复健康后,在第 4 个节点上重启 ClusterBackup,使其从新 leader 恢复异步复制。
  • 数据缺口意识: 异步备份可能落后于实时集群。任何已被集群接受但尚未复制到备份节点的消息都会丢失。缺口大小取决于复制频率和网络延迟。
  • 在将备份数据复制到所有节点之前,切勿启动集群节点——以各节点状态不一致的方式启动可能导致进一步损坏。
  • snapshot 一致性: 务必将完整的 snapshot 与其对应的日志录制一同使用。切勿混用不同时间点的 snapshot 和日志。
  • 定期在非生产环境中演练此流程,以验证 RTO/RPO 目标。

第 4 个备份节点本身是灾难恢复中的单点故障。如果在集群也宕机的同时备份节点的磁盘损坏,你就失去了最后的退路。建议的做法是在 Aeron ClusterBackup agent 之上叠加一层外部的、持久化的存储。

建议做法:定期将 snapshot 归档到对象存储

Section titled “建议做法:定期将 snapshot 归档到对象存储”

推荐的策略是定期将备份节点的 snapshot + 录制日志文件归档到持久化的外部存储(例如 AWS S3、GCS、Azure Blob Storage 或远程 NFS/SAN)。

  1. Aeron ClusterBackup 持续将最新的 snapshot 和日志段从集群复制到第 4 个节点的本地磁盘——这是实时且自动的。
  2. 备份节点上的定时任务(cron、systemd timer 或应用级调度器)定期将一份一致的时间点 snapshot 包复制到对象存储。
  3. 保留策略保留 N 份近期归档,清理较旧的归档以控制存储成本。
#!/bin/bash
# backup-to-s3.sh — runs periodically via cron on the 4th backup node
BACKUP_DIR="/path/to/backup-dir"
S3_BUCKET="s3://your-bucket/aeron-cluster-backups"
TIMESTAMP=$(date +%Y%m%dT%H%M%S)
ARCHIVE_NAME="cluster-backup-${TIMESTAMP}.tar.gz"
STAGING_DIR="/tmp/aeron-backup-staging"
# 1. Pause ClusterBackup agent (optional but recommended for consistency)
# Alternatively, take a filesystem-level snapshot (LVM, ZFS, EBS snapshot)
# if pausing is not acceptable
# 2. Create a consistent copy of the backup directory
mkdir -p "$STAGING_DIR"
cp -a "$BACKUP_DIR" "$STAGING_DIR/backup-snapshot"
# 3. Resume ClusterBackup agent (if paused in step 1)
# 4. Compress and upload to S3
tar -czf "/tmp/${ARCHIVE_NAME}" -C "$STAGING_DIR" backup-snapshot
aws s3 cp "/tmp/${ARCHIVE_NAME}" "${S3_BUCKET}/${ARCHIVE_NAME}"
# 5. Clean up staging
rm -rf "$STAGING_DIR" "/tmp/${ARCHIVE_NAME}"
# 6. Prune old backups — keep last 7 days
aws s3 ls "${S3_BUCKET}/" | awk '{print $4}' | sort | head -n -7 | \
xargs -I {} aws s3 rm "${S3_BUCKET}/{}"
echo "Backup archived: ${S3_BUCKET}/${ARCHIVE_NAME}"

通过 cron 调度(例如每 6 小时一次):

Terminal window
0 */6 * * * /opt/scripts/backup-to-s3.sh >> /var/log/aeron-backup-archive.log 2>&1
方案优点缺点
对象存储归档(推荐)持久、带版本、廉价,内置跨区域复制存在轻微的 RPO 缺口(两次归档之间的时间)
EBS/磁盘级 snapshot文件系统一致、快速、无需应用级脚本与云厂商绑定;snapshot 恢复需要时间
ZFS/LVM snapshot + 复制近乎瞬时的一致 snapshot;可复制到远程需要 ZFS/LVM 搭建;运维复杂度更高
rsync 到远程主机简单,使用标准工具非原子操作——若备份正在写入,可能复制到不完整的状态
第二个备份节点(第 5 个节点)Aeron 层面的完全冗余,无需脚本备份基础设施成本翻倍;灾难恢复仍需异地副本
  • 最佳选择:ClusterBackup 运行期间使用文件系统级 snapshot(EBS snapshot、ZFS snapshot、LVM snapshot)——这能在不暂停复制的情况下,得到一份崩溃一致(crash-consistent)的时间点副本。
  • 良好选择: 短暂暂停 ClusterBackup agent,执行 cp -a 复制目录,然后恢复。暂停窗口很短(秒级),在此期间备份节点只是稍稍落后于集群——恢复后会自动追赶。
  • 应避免:ClusterBackup 正在写入时复制备份目录——你可能会归档到一份写到一半、无法使用的 snapshot。
  • 保留策略: 至少保留 3-7 天的归档。对于合规要求严格的环境,保留 30 天以上或按监管要求执行。
  • 监控归档任务: 当 cron 任务失败,或最近一次归档超过预期间隔的 2 倍时发出告警。
  • 监控备份节点延迟: 跟踪备份节点落后于集群 leader 的程度(通过 ClusterBackup 计数器)。若延迟增大,说明备份已陈旧。
  • 定期验证恢复: 从对象存储下载一份归档,将其恢复到测试集群,并验证状态完整性。未经测试的备份不算备份。

网络故障看起来吓人,但大多能自行纠正。Raft 的核心要义就是已提交的数据能在任何分区下存活。真正需要担心的不是干净利落的断开——而是抖动(flapping)。

情形数据丢失风险可用性影响恢复复杂度修复方案
分区——leader 被隔离未提交的消息短暂(选举)低——自动等待多数派分区中的自动选举;旧 leader 自动下台;修复网络
分区——follower 被隔离无(法定人数保持)低——重连后自动追赶修复网络;follower 重连后自动从 leader 追赶
分区——无多数派(对称分裂)无(已提交数据安全)完全不可用,直至重连中——等待或手动恢复网络连通性;集群自动恢复;无需手动数据恢复
间歇性抖动降级(选举风暴)中——调整超时增大选举超时和心跳间隔;修复底层网络不稳定问题;考虑专用集群网络
节点间高延迟降级(提交变慢)低——调整超时增大心跳/选举超时以容忍延迟;优化网络路径;考虑更近的节点摆放
Scenario: Leader isolated (minority partition)
[AZ-1: Leader] ──✕── [AZ-2: Follower A, Follower B]
↓ ↓
Steps down New election → new leader
(can't reach quorum) (has quorum: 2/3)

Raft 的分区处理很优雅:被隔离的 leader 无法提交任何东西(无法定人数),于是它下台。多数派分区选出新 leader 并继续运行。不会丢失任何数据,因为旧 leader 上的未提交条目从未向客户端确认过。

其中两行其实是调优问题,而非故障。节点间高延迟会拖慢提交,因为每次提交都要等待一次跨节点往返——你的 p99 会随网络路径而攀升。抖动会触发选举风暴,反复使集群停滞。两者都可以通过加大心跳和选举超时来解决,让集群能容忍短暂的抖动而不做出反应——代价是故障检测变慢。超时本身不会影响热路径上的 p50/p99;它只决定一次中断会让吞吐停滞多久,集群才恢复。

磁盘是健康集群悄然停滞的地方。有两个目录至关重要,而“leader 磁盘写满”正是会拖垮整个集群的意外。

情形数据丢失风险可用性影响恢复复杂度修复方案
leader 磁盘写满完全不可用(无法提交)释放磁盘空间或扩容卷;触发 snapshot 以压缩日志;设置磁盘用量告警
follower 磁盘写满无(法定人数保持)释放 follower 上的磁盘空间;写入恢复后节点自动追赶
磁盘损坏(单个节点)无(若被检测到)无(法定人数保持)中——重建节点停止节点;清空损坏的 clusterDir + archiveDir;重启——通过 snapshot 复制 + 日志追赶从 leader 重建
磁盘损坏(所有节点)完全不可用严重——需要外部备份从外部备份恢复所有节点;若无备份,数据丢失
集群目录丢失(单个节点)无(法定人数保持)彻底清空节点;重启——从 leader snapshot + 日志重新置备
集群目录丢失(所有节点)完全不可用严重从外部备份恢复集群元数据;从备份的 snapshot + 日志重建
archive 目录丢失(单个节点)无(法定人数保持)清空节点;重启——通过 snapshot 复制从 leader 追赶
archive 目录丢失(所有节点)完全丢失完全不可用严重从外部备份恢复 archive 录制;无备份 = 数据完全丢失
  • clusterDir——包含集群元数据、标记文件、共识状态。
  • archiveDir——包含录制的流(日志条目、snapshot)。

两者都至关重要。在单个节点上丢失任意一个都可以从对等节点恢复。在所有节点上同时丢失任意一个则需要外部备份。