客户端要连上 FoundationDB,手里通常只有一份
cluster file:里面是 Coordinators 的
IP:PORT
列表。集群重启、换机器、事务系统换代之后,业务进程仍靠这份列表找到「现在的配置权威」。若把
Coordinators 理解成「又一个
etcd」,会误判两件事:用户数据并不存在 Coordinators 上;每次
set 也不走一轮 Paxos。
本文是系列第 3 篇,钉三件事:Coordinators 持久化什么、Cluster Controller 如何成为招募入口、以及 Paxos 在 FDB 里的职责边界。完整恢复 epoch、旧 Log 封印与 RV 计算留给第 13 篇;Raft 选举教科书见 raft-explained,本文不重讲。
本文是「FoundationDB 内核」系列第 3 篇(共 18 篇)。→ 系列目录
篇目 核心内容 第 2 篇 · Client API 事务契约 第 3 篇 · Coordinator 配置、Paxos 边界、招募 第 4 篇 · Proxy Grv / Commit 与批处理
版本锚定:Zhou et al., SIGMOD 2021 §2.3.1 Control Plane、§2.3.4–2.3.5 Bootstrapping / Reconfiguration;FoundationDB 7.x Architecture(Coordinators、Cluster Controller、Master/Sequencer 招募);Active Disk Paxos 引用 Chockler & Malkhi 等工作(论文 Related Work / 控制面描述)。源码侧角色名在
fdbserver/中可见,本篇以论文与官方架构文档为准。
一、Cluster file:发现配置权威,不是发现数据副本
官方 Architecture:客户端与服务器都通过 cluster file 中的 Coordinators 地址接入;双方用 Coordinators 联系 Cluster Controller。服务器在尚无 Controller 时尝试竞选;客户端则通过 Controller 获取最新的 Grv Proxy / Commit Proxy 列表。
因此 cluster file 的语义是:
- 引导发现:谁是当前配置与成员信息的入口。
- 不是分片路由表:业务 key 落在哪台
Storage Server,由事务系统元数据与 Proxy
提供的映射决定(
\xff系统键空间,第 4、11 篇)。 - 可变更但仍须可达多数:Coordinators 集合变更是运维级操作;错误缩减多数会失去配置仲裁。
flowchart LR
client["Client"]
servers["fdbserver processes"]
coord["Coordinators<br/>cluster file endpoints"]
cc["Cluster Controller"]
client -->|"cluster file"| coord
servers -->|"cluster file"| coord
coord -->|"elect / locate"| cc
cc -->|"proxy list / roles"| client
cc -->|"recruit roles"| servers
1.1 Coordinators 上有什么
论文 §2.3.1:控制面把事务系统配置等关键系统元数据持久化在 Coordinators 上;Coordinators 组成 disk Paxos 组,并选出单例 Cluster Controller。
Bootstrapping 链条(论文 §2.3.4)进一步说明分层存放:
| 信息 | 主要存放位置 |
|---|---|
用户数据与大部分系统元数据(0xFF
前缀等) |
Storage Servers |
| Storage Server 相关元数据 | 经由 Log / 恢复路径进入事务系统状态 |
| Log System 配置(有哪些 Log Server) | Coordinators(配置权威) |
一句话:Coordinators 记住「这一代事务/日志系统长什么样」,而不是替 Storage 存业务 KV。
二、Cluster Controller:单例编排器
Cluster Controller 由 Coordinators 多数选举产生(官方 Architecture;论文称 disk Paxos 组选出 singleton)。它的职责包括:
- 作为集群进程的入口与成员视图维护者。
- 失败检测:判断进程是否仍存活。
- 角色招募:告诉进程应承担哪些 role。
- 在进程间传递系统信息。
论文 §2.3.1:Controller 招募三个单例——Sequencer、Data Distributor、Ratekeeper;它们失败后会被重新招募。官方文档补充:自 6.2 起,Data Distributor 与 Ratekeeper 的生命周期不再与 Master/Sequencer 进程绑死,而是由 Cluster Controller 监控的独立单例。
flowchart TB
coord["Coordinators<br/>Paxos group"]
cc["Cluster Controller<br/>singleton"]
seq["Sequencer / Master"]
dd["Data Distributor"]
rk["Ratekeeper"]
coord -->|"elect"| cc
cc -->|"recruit"| seq
cc -->|"recruit"| dd
cc -->|"recruit"| rk
2.1 谁招募 Proxy、Resolver、TLog
论文有一处「历史原因」表述:Sequencer 同时负责招募 Proxies、Resolvers 与 LogServers(§2.3.2)。官方 Architecture 则描述:Master 协调写子系统换代;写子系统包括 master、GRV proxies、commit proxies、resolvers、transaction logs;其中若干角色作为整体替换。
对本系列读者,记住操作语义即可:
- Cluster Controller 保证有一个活着的 Sequencer(Master)世代。
- 该世代的 Sequencer 拉起与自己绑定的 Proxy / Resolver / Log 集合。
- 任一生死监控范围内的角色失败,常触发整代事务系统恢复,而不是只热修单个进程(论文 §2.3.5「Make failure a common case」)。
细节状态机见第 13 篇;本篇只钉「配置权威 → Controller → Sequencer → 事务角色」这条招募链。
三、Paxos 边界:配置共识 ≠ mutation 共识
站内 raft-explained 讨论的是复制状态机安全;FDB 控制面用 Active Disk Paxos(论文引用)解决的是另一类问题:少数机器上的配置如何在故障下仍有唯一权威。
| 层级 | 机制 | 复制的对象 |
|---|---|---|
| Coordinators | Disk Paxos / 多数 | 事务系统配置、锁世代等控制面状态 |
| Log Servers | 复制策略(论文:\(f+1\) 等部署选项) | 已提交 mutation 的 WAL |
| Storage Servers | 多副本 shard | 版本化用户数据 |
用户 tr.set 的成功路径是:Resolver
通过 → Log durable → 向客户端确认,并不在
Coordinators 上为每个 mutation 跑 Paxos。Coordinators
在恢复时被 Sequencer
锁定并更新,防止双主世代(论文
§2.4.4)。
flowchart TB
subgraph paxosBoundary ["Paxos boundary"]
cfg["Cluster configuration<br/>and generation lock"]
end
subgraph commitPath ["Per-commit path"]
occ["OCC on Resolvers"]
log["Replicated Log Servers"]
end
subgraph readPath ["Read path"]
ss["Sharded Storage Servers"]
end
cfg -.->|"recruits / epochs"| commitPath
commitPath -.->|"async"| readPath
3.1 重配何时发生
论文 §2.3.5:当事务系统或日志系统出现故障,或数据库配置变更时,走 reconfiguration:Sequencer 监控 Proxies / Resolvers / LogServers,异常则自杀;Cluster Controller 发现后招募新 Sequencer,新 Sequencer 按 bootstrap 流程拉起新一代 TS/LS,并把新配置写入 Coordinators。
官方 Architecture 补充工程细节:恢复会 快进时间约
90 秒,使进行中的客户端事务因
transaction_too_old
失败并在重试时挂到新世代——这把「旧 Proxy
是否还在发版本」类问题收束到统一客户端重试路径。
常见误解
- 「Coordinators 像
ZooKeeper,所有元数据都在上面」。大部分系统元数据在
Storage 的
\xff空间;Coordinators 关键是事务/日志系统配置与控制面仲裁。 - 「FDB 不用共识」。控制面用 Paxos;数据面提交用日志复制 + OCC。去掉的是「每个写都在 \(2f+1\) 上投票掩盖故障」的默认策略(论文 Abstract)。
- 「改 cluster file 里的地址等于完成扩容」。进程角色由 Controller / Sequencer 招募与数据分布决定;只改文件而不完成协调员变更与进程加入流程,会导致发现失败或脑裂风险。
四、学术谱系与开放问题
谱系:磁盘 Paxos / Active Disk Paxos 把稳定存储上的共识从「内存进程 + 不稳定网络」变体中分出(Chockler & Malkhi 等;论文控制面引用)。FoundationDB 把它用在窄接口:只仲裁配置与世代,把高频事务路径留给无锁 OCC + 日志。
与 TiKV / PD 对照:TiKV 用 PD 存 Region 路由并用 etcd/Raft 管 PD;每次写仍进 Region Raft 组。FDB 用 Coordinators 管事务系统世代,写进 Log Server 集合。两者都有「元数据服务」,但 写路径是否每值走共识组 不同——第 5、18 篇继续对照。
开放问题:急切重配降低副本数需求,却把可用性与 MTTR 绑定(论文原则 Fail fast)。在广域、高抖动网络下,误检导致的频繁世代切换是否可接受,是部署拓扑选择问题,而非单纯调大超时能消掉。第 13、16 篇从恢复与运维再写。
五、bootstrap 故事:空集群如何长出一代事务系统
用论文 §2.3.4 的顺序把「第一次有事务系统」讲成可记忆的故事(生产升级/恢复是同一骨架的变体):
- 进程们拿着同一份 cluster file 找到 Coordinators;尚无 Cluster Controller 时,服务器竞选,Paxos 组选出 Controller。
- Controller 招募 Sequencer(以及 Data Distributor、Ratekeeper)。
- 新 Sequencer 读 Coordinators 里记录的旧 Log System 配置(若有),拉起新的 Proxy / Resolver / Log 集合,并从旧日志路径恢复系统元数据(含 Storage 信息)。
- 恢复完成后,Sequencer 把新 LS 配置写回 Coordinators。
- 此后客户端经 Controller 拿到 Proxy 列表,才能稳定取版本与提交。
sequenceDiagram
participant S as fdbserver
participant Co as Coordinators
participant CC as Cluster Controller
participant Seq as Sequencer
S->>Co: locate / elect CC
Co-->>CC: elected
CC->>Seq: recruit
Seq->>Co: read prior LS config
Seq->>Seq: spawn TS and LS
Seq->>Co: write new LS config
Note over Seq: Ready for client commits
没有外部依赖(ZooKeeper / etcd)是刻意选择:配置权威内建在 Coordinators,避免「元数据服务的元数据服务」递归。代价是协调员集合本身必须被正确运维——丢多数等于丢配置仲裁。
5.1 与 raft-explained 的接缝
raft-explained 证明的是:已提交日志在何种投票规则下不会被覆盖。FDB 控制面要的是:同一时刻至多一个世代持有配置锁。二者都是共识,但复制对象与频率差几个数量级。读本系列时,把「共识」一词默认加上宾语——共识的是配置,还是用户 mutation。
5.2 运维上容易踩的坑(机制向)
下列条目来自官方架构语义的推论,不是本站事故复盘:
- 协调员多数不可用:无法选举或锁定配置,事务系统无法安全换代。
- cluster file 与真实协调员集不一致:部分客户端连旧集、部分连新集,表现为间歇性无法发现 Proxy。
- 把 Coordinators 当监控中心疯狂轮询:控制面为低频元数据设计;发现路径应缓存 Controller / Proxy 列表并在错误时刷新。
- 假设「只重启一台 Storage」等于「只丢读容量」:若同机还共址了 Sequencer/Proxy,可能触发写子系统恢复——共址策略要把故障域考虑进去(第 16 篇)。
flowchart LR
bad1["Stale cluster file"] --> sym1["Cannot find healthy proxies"]
bad2["Lost coordinator quorum"] --> sym2["Cannot reconfigure safely"]
bad3["Colocated sequencer death"] --> sym3["Write epoch recovery"]
5.3 配置变更与事务世代的关系
官方把数据库配置变更也列为触发 reconfiguration 的原因之一(与进程失败并列,论文 §2.3.5)。含义是:改复制因子、改日志相关配置等,往往不是「热更新局部参数」,而是换一代事务系统。运维窗口应按「可能写暂停数百毫秒到数秒」来预留,而不是按「改一下 conf 无感」来预留。具体操作步骤以 7.x Administration 文档为准;本系列只钉机制:配置写在 Coordinators,生效路径经过 Sequencer 换代。
把 Coordinators 想成「低频、高后果」组件:改错一次的爆炸半径是控制面,不是某一个 shard。备份 cluster file、变更时维护多数、变更后验证客户端都能发现新 Proxy 列表,是机制推论出的操作纪律。
与第 1 篇 Unbundled 全景对照:数据面可以水平加 Storage / Proxy,但控制面的正确性前提是 Coordinators 多数一直在。扩容叙事里先保证协调员与 Controller 健康,再谈加 Storage。第 13 篇会回到「换代时写暂停、读边界」的精确语义。
(本篇不展开 Active Disk Paxos 的消息图;需要协议细节时回到论文引用与 raft-explained 的安全不变量对照即可。)
六、小结
三句话小结
- Coordinators 经 cluster file 对外暴露,用磁盘 Paxos 持久化事务系统配置并选举 Cluster Controller;它们不是业务 KV 的存放地。
- Cluster Controller 招募 Sequencer / Data Distributor / Ratekeeper;Sequencer 再拉起与本世代绑定的 Proxy、Resolver、Log Server。
- Paxos 的边界停在配置与世代锁;用户提交走 OCC + Log 复制。完整恢复状态机见第 13 篇。
下一篇进入客户端每天实际打到的入口:Proxy:读版本与提交入口。
参考资料
核心论文
- Zhou et al., SIGMOD 2021, §2.3.1–2.3.5、§2.4.4(控制面、bootstrap、reconfiguration、recovery lock)。
规范 / 文档
- FoundationDB Architecture — Coordinators、Cluster Controller、Master、Transaction System Recovery(7.x)。
- FoundationDB Administration 文档 — cluster file、coordinator 变更(7.x,运维步骤以官方为准)。
站内
- raft-explained(共识安全;本篇不重讲)。
- 第 1 篇 Unbundled 全景。
- 本系列 index。
上一篇:Client API 与事务模型
下一篇:Proxy:读版本与提交入口
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【FoundationDB 内核】故障恢复:角色招募与恢复 epoch
按 SIGMOD 2021 钉住 FoundationDB 把失败收敛到同一条恢复路径:Sequencer 锁定 Coordinator、停止旧 LogServer、招募新 Proxy/Resolver/TLog、确定 RV/PEV,并说明写暂停、读边界与旧角色隔离。
【FoundationDB 内核】Sequencer:read/commit version、逻辑单点与恢复
说明 Sequencer 如何分配 read version 与 commit version、为何是逻辑单点而非无高可用,以及世代恢复如何与版本推进衔接。
【FoundationDB 内核】严格可串行化与 5 秒限制:实时顺序与恢复有界性
说明 FoundationDB 如何用 Sequencer 版本把 OCC+MVCC 提升到严格可串行化,区分 serialization order 与实时顺序;论证 5 秒事务上限如何约束冲突窗口与恢复日志量,并点明高冲突下的开放问题。
【FoundationDB 内核】Transaction Log:提交点、durable version 与异步解耦
拆解 FoundationDB Transaction Log(TLog)如何作为分布式 WAL:按复制策略同步 durable 后 Commit Proxy 才返回成功;说明 durable version、known committed version 与恢复版本的关系,以及 Storage Server 异步消费如何离开提交临界路径。