Storage Controller 自动故障切换机制
Storage Controller 是自动完成故障切换的。
1. 心跳检测 → 标记离线
// storage_controller/src/heartbeater.rs:281 if now - *last_seen_at >= self.max_offline_interval { // 超过 30 秒无心跳 →标记为 Offline deltas.push((*node_id, ps_state.clone())); }默认配置:
- 心跳间隔:HEARTBEAT_INTERVAL_DEFAULT = 5 秒
- 离线判定:MAX_OFFLINE_INTERVAL_DEFAULT = 30 秒
时间线:
- T=0s:心跳正常
- T=5s:心跳正常
- T=10s:心跳正常
- ...
- T=35s:主节点故障,无心跳
- T=40s:Storage Controller 检测到离线(30秒超时)
- 触发故障切换流程
2. 自动提升 Secondary 为主
// storage_controller/src/tenant_shard.rs:678-682 if let Some(promote_secondary) = self.preferred_secondary(scheduler) { // 自动从 Secondary 中选择一个提升到 Attached self.intent.promote_attached(scheduler, promote_secondary); Ok((true, promote_secondary)) }提升逻辑:
- 检测主位置节点离线
- 从 Secondary 列表中选择一个可用节点
- 调用 promote_attached():
- 从 secondary 列表移除
- 设置为新的 attached
- 原主节点降级为 secondary(如果恢复)
3. 完整的故障切换流程
主位置(Node A)故障
主位置(Node A)故障 │ ▼ ┌─────────────────────────────────────────────────────┐ │ Storage Controller 自动检测 │ │ │ │ 1. 心跳超时(30秒)→标记 Node A 为 Offline │ │ 2. 触发 Reconciler 重新规划 │ │ 3. 发现 Attached 为空,Secondary 列表非空 │ │ 4. 调用 promote_attached(Node B) │ │ │ └─────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 故障切换执行 │ │ │ │ Node A(原主位置): │ │ →降级为 Secondary(warm=true) │ │ →继续缓存层文件,等待恢复后重新加入 │ │ │ │ Node B(原次级位置): │ │ →升级为 Attached(generation+1) │ │ →从 S3 加载缓存的层文件 │ │ →从 Safekeeper 追 WAL(LSN X →current) │ │ →服务查询 │ │ │ │ Compute 连接: │ │ →Storage Controller 通知 Compute 切换 Pageserver │ │ →客户端重连到新 Pageserver │ └─────────────────────────────────────────────────────┘关键代码位置
| 功能 | 文件 | 函数 |
|---|---|---|
| 心跳检测 | storage_controller/src/heartbeater.rs:281 | heartbeat_loop() |
| 离线判定 | storage_controller/src/service.rs:127 | max_offline_interval |
| 自动提升 | storage_controller/src/tenant_shard.rs:678 | schedule() |
| 切换执行 | storage_controller/src/tenant_shard.rs:226 | promote_attached() |
| 重新规划 | storage_controller/src/reconciler.rs:79 | reconcile_tenant_shard() |
总结
| 问题 | 答案 |
|---|---|
| 是否自动故障切换? | ✅ 是,Storage Controller 自动完成 |
| 检测延迟多久? | 默认 30 秒(心跳间隔 5 秒 ×6 次超时) |
| 切换方式? | 自动将 Secondary 提升为 Attached |
| 原主节点恢复后? | 降级为 Secondary,重新预热缓存 |
| 是否需要人工干预? | ❌ 不需要,完全自动化 |