Engine execution layer for V2 replication protocol: - RebuildInstaller: full state handoff (dirty map, WAL, superblock, flusher) - TruncateToLSN: exact safety predicate (checkpointLSN == truncateLSN), ErrTruncationUnsafe escalation to NeedsRebuild - SyncReceiverProgress: unconditional Store for post-rebuild alignment - V2StatusSnapshot: CommittedLSN = nextLSN-1 for sync_all V2 bridge real I/O executors: - TransferFullBase: TCP streaming + RebuildInstaller + second catch-up - TransferSnapshot: SHA-256 verified streaming to disk - TruncateWAL: ErrTruncationUnsafe detection + escalation - StreamWALEntries: rebuild-mode TCP apply Engine executor interfaces: - CatchUpIO.TruncateWAL, RebuildIO.TransferFullBase returns achievedLSN - CatchUpExecutor truncation-only skip, NeedsRebuild escalation - RebuildExecutor uses achievedLSN for progress tracking Design docs reorganized: superseded planning docs removed, protocol truths and closure map added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
16 KiB
V2 协议闭环图
日期:2026-04-02 状态:active 读者:架构设计、实现负责人、tester、reviewer
1. 文档目标
这份文档不是单纯介绍算法。
它的目标是把 V2 在当前 chosen path 上的协议结构整理成一张“闭环图”,回答下面几个问题:
V2当前有哪些正式状态对象- 这些对象之间有哪些关键事件和迁移
V2当前维持哪些语义约束- 这些约束分别由哪些证明义务支撑
- 这些证明义务已经映射到哪些 phase / slice / 实现点 / 测试点
这份文档想说明的是:
V2不是一组散乱 patch- 而是在明确边界内逐步建立的协议闭环
这里的“闭环”是有范围的。
当前默认边界仍然是:
RF=2sync_all- 现有 master / volume-server heartbeat path
blockvol作为当前执行 backend
所以本文不宣称“所有模式全部完备”。 它宣称的是:
- 在 chosen path 上,
V2已经建立了一个结构化、可验证、可扩展的协议闭环框架
1.1 五层模型总览(Mermaid)
自上而下:从代码与运行时,到语义、证明与工程落地(读图:下层是承载,上层是约束与 close)。
flowchart TB
subgraph L1["Layer 1 物理实现"]
I1[master / VS / gRPC / blockvol]
end
subgraph L2["Layer 2 状态机"]
S1[控制 / 恢复 / 数据边界 / 上报]
end
subgraph L3["Layer 3 语义约束"]
C1[ownership]
C2[identity]
C3[boundary]
C4[convergence]
C5[idempotence]
end
subgraph L4["Layer 4 证明义务"]
P1[约束 → 最小证据包]
end
subgraph L5["Layer 5 工程映射"]
E1[实现点]
E2[观测点]
E3[测试 / one-chain]
E4[phase / slice]
end
L1 --> L2
L2 --> L3
L3 --> L4
L4 --> L5
2. V2 的五层模型
Layer 1:物理实现层
这一层列出当前承载 V2 truth 的真实工程对象。
2.1 主要实现对象
- master 侧:
master_grpc_server.gomaster_grpc_server_block.gomaster_block_failover.goBlockAssignmentQueue
- volume server 侧:
volume_grpc_client_to_master.govolume_server_block.goCollectBlockVolumeHeartbeat()
- V2 控制 / 恢复桥接:
v2bridge/control.goRecoveryManager
- V2 执行层:
CatchUpExecutorRebuildExecutorv2bridge/executor.go
- backend 执行层:
blockvolWALsnapshotflusher
2.2 这一层的意义
这一层回答的是:
- 协议最终在哪些真实代码路径里运行
- 哪些对象是真正的 authority carrier
- 哪些地方是观测点
但它本身不定义协议语义。
Layer 2:状态机层
这一层定义 V2 的正式状态对象与关键事件。
2.3 控制面状态对象
| 对象 | 作用 | 典型字段 |
|---|---|---|
| Assignment truth | master/VS 之间的控制意图 | Path, Epoch, Role, replica identity, replica addrs |
| Stable identity | 防止地址形态混淆 authority | ServerID, local server identity |
| Role truth | 定义当前是 primary / replica / rebuilding | Role, LeaseTtlMs |
2.4 恢复状态对象
| 对象 | 作用 | 典型状态 |
|---|---|---|
| Sender | V2 的恢复主体 | in_sync, catchup, needs_rebuild, disconnected |
| Session | 一次恢复意图的 authority 载体 | created, superseded, removed |
| Recovery task | live runtime owner | running, draining, done |
2.5 数据边界状态对象
| 对象 | 作用 |
|---|---|
CommittedLSN |
当前对外可承诺、可用于 recovery 目标的边界 |
CheckpointLSN |
稳定物化边界 |
WALHeadLSN |
当前 WAL 最高边界 |
receivedLSN |
receiver 当前已连续接收边界 |
targetLSN |
recovery plan 的目标边界 |
achievedLSN |
实际 rebuild / transfer 达到的边界 |
snapshotBaseLSN |
snapshot 所代表的基线边界 |
2.6 对外可见状态对象
| 对象 | 作用 |
|---|---|
| Heartbeat truth | VS 对 master / 外部报告的 block 状态 |
| Reported replica addr | 当前 externally visible replica truth |
| Reported role / epoch | 当前 externally visible control truth |
2.7 关键事件
当前 chosen path 上最关键的事件包括:
AssignmentDeliveredEpochBumpedSessionCreatedSessionSupersededSessionRemovedCatchUpPlannedCatchUpCompletedRebuildStartedRebuildCommittedSnapshotTransferredTruncationEscalatedRepeatedAssignmentDeliveredHeartbeatCollected
2.8 Truth 流水线(Mermaid)
V2 的主要工作,是保证这条链上的各层 truth 在关键场景下不长期分裂(no persistent split truth)。
flowchart TD
MT[master truth\nassignment 意图]
AD[assignment delivery\nproto / heartbeat / gRPC]
VI[VS ingest truth\nAssignmentsFromProto → ProcessAssignments]
ES[engine / session truth\norchestrator / sender]
RO[runtime ownership truth\nRecoveryManager / tasks]
DB[data-boundary truth\nLSN / checkpoint / achieved]
HB[heartbeat / reporting truth\nCollectBlockVolumeHeartbeat]
MT --> AD
AD --> VI
VI --> ES
ES --> RO
RO --> DB
DB --> HB
文字版(与上图一致):
master truth → delivery → VS ingest → engine/session → runtime owner → data boundary → heartbeat/reporting
2.9 V1 与 V2:哪些“未显式状态”会让结果不确定
这一节用同一套 truth 流水线来对比:不是比较“代码行数”,而是比较协议层是否显式持有状态。
下列概括针对常见 V1 工程形态与 V2 chosen-path 显式化 的对比,用于直觉理解;具体实现细节以代码与 phase 证据为准。
| Truth 环节 | V1 常见风险(状态隐含时) | V2 显式化后更可回答的问题 |
|---|---|---|
| master truth | 仅地址/临时约定,failover 后身份易混淆 | stable ServerID 与 epoch 是否一致 |
| delivery | 重复投递、重复副作用 | 同 truth 是否幂等(P3) |
| VS ingest | 隐式 fallback 成地址身份 | 是否 fail-closed(P1) |
| engine/session | 旧 session 与新 session 边界不清 | supersede 后旧 authority 是否失效 |
| runtime owner | goroutine 级“好像还在跑” | 是否 serialized drain(Phase 09 P4) |
| data boundary | “完成”与本地 LSN 不一致 | achievedLSN 与 checkpoint/receiver 是否收敛(Phase 09 P1) |
| heartbeat | 上报与控制意图漂移 | 与 assignment 是否一致(Phase 10 P2) |
不确定性的典型结构:
flowchart LR
subgraph V1style["状态未显式时"]
U1[身份弱]
U2[owner 弱]
U3[边界弱]
end
subgraph out["表现"]
X1[时序敏感]
X2[重试改变结果]
X3[split truth]
end
V1style --> out
一句话:V1 在很多路径上仍然可用,但上述环节一旦缺少显式对象,系统在边界场景下会更容易出现结果不确定(依赖时序、依赖重试、或内部 truth 与外部报告不一致)。V2 的方向是把它们变成可命名状态 + 可证义务。
更细的“方法层”叙述见:v2-semantic-methodology.zh.md 第 10 节。
Layer 3:语义约束层
这一层定义协议必须长期维持的核心约束。
3.1 Ownership constraints
目标:
- 明确当前谁拥有 recovery authority
当前约束:
- 同一 replica 不能同时存在两个合法 live owner
- supersede 后旧 owner 必须失效
- shutdown 后不得残留 live owner
- 旧 session 不能在新 truth 下继续提交有效结果
3.2 Identity constraints
目标:
- 不用 transport address 猜身份
当前约束:
- stable
ServerID是 control truth 的正式部分 ReplicaID应从<path>/<ServerID>构造- 缺失 stable ID 时 chosen path 应 fail closed
- local server identity 应使用 canonical
volumeServerId
3.3 Boundary safety constraints
目标:
- rebuild / snapshot / truncate 的边界必须物理成立
当前约束:
- full-base rebuild 的完成边界必须显式暴露并与 runtime 对齐
- snapshot rebuild 的边界必须由 manifest / hash / base LSN 约束
- truncation 只有在安全条件成立时才允许本地修复
- 做不到安全修复时必须 escalate,而不是伪装成功
3.4 Convergence constraints
目标:
- 不允许长期 split truth
当前约束:
- assignment truth、runtime truth、heartbeat truth 必须收敛
- reassignment 后旧 truth 不应继续对外可见
achievedLSN、checkpoint、receiver progress 在 accepted contract 下应收敛- control truth 变化后,旧 runtime residue 不应残留
3.5 Idempotence constraints
目标:
- 同样 truth 重复出现时,不应不断产生额外副作用
当前约束:
- repeated unchanged assignment 不应重复触发 recovery
- repeated unchanged delivery 不应重复 relisten / restart
- repeated delivery 不应破坏已收敛的 truth
Layer 4:证明义务层
这一层把上述语义约束变成“必须被证明”的义务。
4. 当前主要证明义务地图
| 语义约束 | 证明义务 | 对应 phase / slice | 当前状态 |
|---|---|---|---|
| ownership | old owner 被 drain,replacement 前不得重叠 | Phase 09 P4 |
accepted |
| ownership | shutdown 后 active task = 0 | Phase 09 P4 |
accepted |
| identity | stable ID survives proto/decode/ingress | Phase 10 P1 |
accepted |
| identity | missing stable ID fails closed | Phase 10 P1 |
accepted |
| convergence | reassignment 后 old sender removed / new sender present | Phase 10 P2 |
accepted |
| convergence | heartbeat truth 收敛到新 replica truth | Phase 10 P2 |
accepted |
| convergence | stale runtime residue removed | Phase 10 P2 |
accepted |
| idempotence | repeated unchanged assignment 不增加 V2 side effect | Phase 10 P3 |
accepted |
| idempotence | repeated unchanged assignment 不重复 V1 relisten/setup | Phase 10 P3 |
accepted |
| boundary safety | full-base achieved boundary 与 runtime/engine accounting 对齐 | Phase 09 P1 |
accepted |
| boundary safety | snapshot boundary exactness and fail-closed | Phase 09 P2 |
accepted |
| boundary safety | unsafe truncate escalates to rebuild | Phase 09 P3 |
accepted |
| control-loop closure | master-originated truth through fuller heartbeat/gRPC loop | Phase 10 P4 |
accepted |
4.1 证明义务不是穷举
这里的义务不是说:
- 所有状态空间已经被穷举证明
而是说:
- 在 chosen path 上,关键协议约束都被映射成了具体、可检查、可 close 的证明义务
这比“随机多跑一些 case”更强,因为它更明确。
5. 已经关闭的主要协议闭环
为了更直观,可以把当前 accepted 闭环按主题来看。
5.1 Recovery ownership 闭环
已关闭:
- live recovery owner 的 start / cancel / replace / drain
- stale owner removal
- no overlap replacement
主要来源:
Phase 09 P4Phase 10 P2
5.2 Identity/control truth 闭环
已关闭:
- stable ID on wire
- local canonical identity
ReplicaID不再依赖 address fallback- missing ID fail closed
主要来源:
Phase 10 P1
5.3 Boundary safety 闭环
已关闭:
- full-base rebuild achieved boundary closure
- snapshot exact-boundary closure
- truncation safe/unsafe split and escalate
主要来源:
Phase 09 P1Phase 09 P2Phase 09 P3
5.4 Reassignment / convergence 闭环
已关闭:
- reassignment 后 old sender removed
- new sender created
- heartbeat truth updated
- stale runtime residue removed
主要来源:
Phase 10 P2
5.5 Repeated unchanged truth 闭环
已关闭:
- repeated unchanged assignment is idempotent
- no duplicate orchestrator/recovery side effects
- no duplicate relisten/setup side effects
主要来源:
Phase 10 P3
6. 当前仍然开放的闭环
当前主要剩余的 open item 是:
6.1 Master-driven control-loop closure
问题不是 VS 本地处理是否成立,而是:
- master 产生的 truth 是否经过真实 heartbeat / gRPC loop 到达 VS
- 到达后是否仍保持 accepted identity / convergence / idempotence
- 对外报告是否仍与同一 master-originated truth 一致
当前对应 slice:
Phase 10 P4
这是当前协议闭环图上最大的未关闭项。
Layer 5:工程映射层
这一层把抽象对象映射回真实实现、观测点和测试。
7. 语义对象到实现点的映射
| 语义对象 / 约束 | 主要实现点 | 主要观测点 | 主要测试/证据 |
|---|---|---|---|
| Stable identity | master.proto, block_heartbeat_proto.go, v2bridge/control.go |
sender registry, local server ID | qa_block_identity_test.go |
| Assignment ingress | AssignmentsFromProto(), ProcessAssignments() |
engine sender / role application | qa_block_identity_test.go, qa_block_convergence_test.go |
| Recovery ownership | block_recovery.go |
task map, done channel, sender state | block_recovery_test.go |
| Reassignment convergence | ProcessAssignments(), CollectBlockVolumeHeartbeat() |
sender registry, runtime task map, heartbeat output | qa_block_convergence_test.go |
| Repeated-assignment idempotence | volume_server_block.go assignment tracking |
V2 event log, repl state, heartbeat output | qa_block_idempotence_test.go |
| Full-base boundary closure | v2bridge/executor.go, blockvol rebuild install path |
checkpoint, head, achieved progress | transfer_test.go / one-chain tests |
| Snapshot boundary closure | snapshot export/import path | base LSN, hash, post-install convergence | snapshot rebuild tests |
| Truncation safety | TruncateToLSN(), executor escalation path |
sender state, local LSN state | truncation tests |
8. Phase 到语义约束的映射
8.1 Phase 09
Phase 09 的主题是:
- backend execution closure
它主要关掉的是:
- boundary safety
- recovery execution realism
- live runtime ownership
8.2 Phase 10
Phase 10 的主题是:
- control-plane closure
它主要关掉的是:
- identity truth
- reassignment convergence
- idempotence
- fuller master-driven control-loop proof
9. 一个简化的“从语义到开发”流程
如果以后再开新 slice,可以用下面这个框架:
9.1 先定义状态对象
例如:
- assignment truth
- runtime owner
- heartbeat truth
9.2 再定义关键事件
例如:
- epoch bump
- repeated delivery
- crash / restart
9.3 再定义要关闭的语义约束
例如:
- no split truth
- fail closed
- idempotence
9.4 再写证明义务
例如:
- old owner drained
- unsafe path escalates
- repeated unchanged truth does not create side effects
9.5 最后才写实现和测试
例如:
- 改哪个入口点
- 观测哪个 runtime / heartbeat / event log
- 用哪种 one-chain proof close
10. 这份闭环图想表达什么
它想表达的不是:
V2所有模式全部完成
它想表达的是:
V2已经有正式状态对象,而不是只靠代码隐含状态V2已经有显式语义约束,而不是主要靠补 bug 建立正确性V2已经把关键 correctness 问题写成证明义务,而不是只靠随机 caseV2已经把这些义务映射回 phase、实现点和测试点- 在 chosen path 上,协议闭环已经大体成形,只剩有限 open item
11. 推荐和哪些文档一起阅读
建议按下面顺序阅读:
v2-semantic-methodology.zh.mdv2-detailed-algorithm.zh.mdv2-protocol-closure-map.zh.mdv2-product-completion-overview.mdv2-phase-development-plan.md
这样可以依次看到:
- 方法
- 算法
- 闭环地图
- 产品完成度
- phase 推进计划