Files
seaweedfs/sw-block/design/v2-algorithm-overview.zh.md
T
pingqiuandClaude Opus 4.6 46ef79ce35 fix: stable ServerID in assignments, fail-closed on missing identity, wire into ProcessAssignments
Finding 1: Identity no longer address-derived
- ReplicaAddr.ServerID field added (stable server identity from registry)
- BlockVolumeAssignment.ReplicaServerID field added (scalar RF=2 path)
- ControlBridge uses ServerID, NOT address, for ReplicaID
- Missing ServerID → replica skipped (fail closed), logged

Finding 2: Wired into real ProcessAssignments
- BlockService.v2Bridge field initialized in StartBlockService
- ProcessAssignments converts each assignment via v2Bridge.ConvertAssignment
  BEFORE existing V1 processing (parallel, not replacing yet)
- Logged at glog V(1)

Finding 3: Fail-closed on missing identity
- Empty ServerID in ReplicaAddrs → replica skipped with log
- Empty ReplicaServerID in scalar path → no replica created
- Test: MissingServerID_FailsClosed verifies both paths

7 tests: StableServerID, AddressChange_IdentityPreserved,
MultiReplica_StableServerIDs, MissingServerID_FailsClosed,
EpochFencing_IntegratedPath, RebuildAssignment, ReplicaAssignment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 10:46:17 -07:00

18 KiB
Raw Blame History

V2 算法综述

日期:2026-03-27 状态:战略级设计综述 读者:CEO / owner / 技术管理层

文档目的

本文用于说明 sw-block 当前 V2 方向背后的核心判断:

  • V2 到底想解决什么问题
  • 为什么 V1 / V1.5 不足以作为长期架构
  • 为什么我们仍然认为基于 WAL 的方向值得继续走
  • V2 与主要市场方案 / 论文路线相比的取舍是什么
  • simulation 与真实 test runner 如何形成系统化验证闭环

这不是 phase 汇报,也不是对生产可用性的承诺文档。

它是对 V2 这条架构线的高层技术解释。

与其他文档的关系

文档 作用
v1-v15-v2-comparison.md 三条技术线的详细比较
v2-acceptance-criteria.md V2 协议验证下限
v2_scenarios.md 场景清单与 simulator 覆盖
v2-open-questions.md 仍未关闭的算法问题
protocol-development-process.md 协议开发方法论
learn/projects/sw-block/algorithm_overview.md 当前 V1/V1.5 系统级算法综述
learn/projects/sw-block/design/algorithm_survey.md 论文 / vendor 调研与借鉴项
learn/projects/sw-block/test/README.md 真实测试系统入口
learn/projects/sw-block/test/test-platform-review.md test runner 的平台化方向

1. 执行摘要

当前最准确的结论是:

  • V1 证明了基于 WAL 的复制块存储基本路径是可行的。
  • V1.5 在真实恢复场景上已经比 V1 明显更强,并且有真实硬件上的运行证据。
  • V2 的意义,不是在已有逻辑上继续打补丁,而是把最关键的恢复与一致性问题直接上升为协议对象。

V2 的核心想法可以概括为:

  • 短间隙恢复要显式
  • 过期 authority 要显式 fencing
  • catch-uprebuild 的边界要显式
  • 恢复 ownership 要成为协议的一部分,而不是实现细节里的偶然行为

所以今天正确的策略是:

  • 继续用 V1.5 作为当前生产线
  • 继续用 V2 作为长期架构线
  • 继续认真研究 WAL 路线,因为现在我们已经具备了可信的验证框架
  • 如果后续 prototype 证明 V2 有结构性缺陷,就应当先演进到 V2.5,而不是硬着头皮直接实现

2. V2 真正要解决的问题

从前端看,块存储似乎只有几个简单动作:

  • write
  • flush / sync
  • failover
  • recovery

但真正难的,不是这些前端动作本身,而是异步分布式边界:

  • primary 本地 WAL 追加
  • replica 端 durable progress
  • client 可见的 sync / commit 真值
  • failover / promote 时的数据边界
  • lag、restart、address change、timeout 后的恢复正确性

这才是 V2 存在的根因。

项目已经反复验证过:块存储真正的 bug 通常不出在 happy path,而出在:

  • replica 短暂掉线又回来
  • replica 重启后地址变化
  • 延迟到达的 stale barrier / stale reconnect 结果
  • 一个 lagging replica 看起来“差一点点就能恢复”
  • failover 时基于错误 lineage 做了 promote

V2 就是要把这些情况变成协议的第一公民,而不是上线后再继续被动修补。

3. 为什么 V1 / V1.5 不够

这份综述不需要长篇回顾 V1V1.5 的所有细节。

只需要讲清它们为什么不足以作为长期架构。

V1 做对了什么

V1 建立了最重要的基础:

  • 严格有序的 WAL
  • primary-replica 复制
  • 基于 epoch + lease 的初步 fencing
  • extent 作为稳定数据面,而不是一开始就做全日志结构

V1 的不足

它的关键短板主要在恢复与退化场景:

  • 短 outage 很容易演化成 rebuild 或长期 degraded
  • 恢复结构过于隐式
  • changed-address restart 脆弱
  • stale authority / stale result 还不是协议层的显式对象
  • 系统没有足够清晰地区分:
    • 当前 head
    • committed prefix
    • recoverable retained range
    • stale / divergent tail

V1.5 的不足

V1.5 已经解决了不少真实问题:

  • retained-WAL catch-up
  • same-address reconnect
  • sync_all 的真实行为
  • catch-up 失败后的 rebuild fallback
  • changed-address restart 之后的 control-plane 刷新

所以它今天是更强的生产线。

但它仍然不是长期架构,因为它本质上仍然是增量修复:

  • reconnect 逻辑仍然附着在旧 shipper 模型上
  • 恢复 ownership 是先作为 bug 暴露出来,再逐步被抽象
  • catch-up vs rebuild 更清楚了,但还不够成为协议顶层契约
  • 整体感觉仍然更像“继续修 V1”,而不是“定义下一代复制协议”

V2 的变化

V2 不是重新发明一个完全不同的存储模型。

它的目标是把最关键的东西显式化:

  • recovery ownership
  • lineage-safe recovery boundary
  • catch-up / rebuild 分类
  • per-replica sender authority
  • stale-result rejection
  • 明确的 recovery orchestration

因此最诚实的比较是:

  • V1.5 今天在运行证据上更强
  • V2 今天在架构质量上更强

这不是矛盾,而是“当前生产线”和“下一代架构线”应有的分工。

flowchart TD
    V1[V1]
    V15[V1_5]
    V2[V2]
    realFailures[真实故障]
    realTests[真实硬件验证]
    simAndProto[仿真与原型]

    V1 --> V15
    V15 --> V2
    realFailures --> V15
    realFailures --> V2
    V15 --> realTests
    V2 --> simAndProto

4. V2 如何解决 WAL 与 Extent 的同步问题

V2 的核心问题不是“还要不要 WAL”。

真正的问题是:

primary 与 replica 之间,WAL 和 extent 如何保持同步,同时还能兼顾稳定性与性能。

这才是 V2 的中心。

4.1 基本分工

V2 把数据路径拆成两个既分离又协作的层:

  • WAL:近期历史的有序真相
  • extent:稳定的物化数据镜像

WAL 负责:

  • 严格写入顺序
  • 本地崩溃恢复
  • 短间隙 replica catch-up
  • 基于 LSN 的 durable progress 计量

Extent 负责:

  • 稳定读镜像
  • 长期存储
  • checkpoint / base image 生成
  • 长间隙恢复时作为真正 base image 的来源

第一条稳定性原则就是:

  • 不要让当前 extent 冒充历史状态
  • 不要让 WAL 永远承担所有长距离恢复责任

4.2 Primary-replica 同步模型

V2 理想中的 steady-state 同步模型是:

  1. primary 分配单调递增的 LSN
  2. primary 本地顺序追加 WAL
  3. primary 把记录放入 per-replica sender loop
  4. replica 按顺序接收并推进显式 progress
  5. barrier/sync 依赖 replica 的 durable progress,而不是 optimistic send progress
  6. flusher 再把 WAL-backed dirty state 物化到 extent

本地 WAL -> extent 生命周期可以理解为:

stateDiagram-v2
    [*] --> WalAppended
    WalAppended --> SenderQueued
    SenderQueued --> ReplicaReceived
    ReplicaReceived --> ReplicaDurable
    ReplicaDurable --> SyncEligible
    SyncEligible --> ExtentMaterialized
    ExtentMaterialized --> CheckpointAdvanced

这里最关键的规则是:

  • client 可见的 sync 真值必须跟随 durable replica progress
  • 不能跟随 send progress
  • 不能跟随 local WAL head
  • 不能跟随“看起来 replica 应该已经收到了”

这也是为什么 V2 使用像 CommittedLSN 这样的 lineage-safe 边界,而不是松散的“当前 primary head”。

4.2.1 不同 sync mode 如何判断结果

V2 让不同 sync mode 的成功条件变得更明确:

  • best_effortprimary 达到本地 durability point 后即可成功,replica 可以后台恢复
  • sync_all:所有 required replica 都要在目标边界上 durable
  • sync_quorum:必须存在真实 durable quorum

其判断路径可以表示为:

flowchart TD
    writeReq[WriteAndSyncRequest]
    localDurable[PrimaryLocalDurable]
    barrierEval[EvaluateReplicaDurableProgress]
    bestEffortAck[best_effort成功]
    syncAllAck[sync_all成功]
    syncQuorumAck[sync_quorum成功]
    rejectOrBlock[阻塞或失败]

    writeReq --> localDurable
    localDurable --> bestEffortAck
    localDurable --> barrierEval

    barrierEval -->|"allRequiredReplicasDurable"| syncAllAck
    barrierEval -->|"durableQuorumExists"| syncQuorumAck
    barrierEval -->|"notEnoughDurableReplicas"| rejectOrBlock

这意味着 sync 结果不再依赖:

  • socket 看起来还活着
  • sender 好像还在发
  • replica 似乎“差不多收到了”

而是依赖显式 durable progress。

4.3 为什么这个设计应该更稳定

它试图把最危险的模糊边界拆开:

  • 写入顺序WAL + LSN 表达
  • durability truth 由 barrier / flushed progress 表达
  • recovery ownership 由 sender + recovery attempt identity 表达
  • catch-up vs rebuild 由显式分类表达
  • promotion safety 由 committed prefix 与 lineage 表达

也就是说,V2 的稳定性来自于减少隐式耦合。

4.4 为什么它仍然可以有高性能

这里不能夸大说 V2 一定在所有情况下都更快。

更准确的性能论点是:

  • 保持 primary 前台写路径简单:
    • 本地顺序 WAL append
    • 投递到 per-replica sender loop
    • 不把复杂恢复逻辑塞进前台写路径
  • 把复杂度主要放在健康热路径之外:
    • sender ownership
    • reconnect classification
    • catch-up / rebuild decision
    • timeout 和 stale-result fencing 主要都在 recovery / control path
  • 让 WAL 只承担它擅长的工作:
    • 近期 ordered delta
    • 短间隙 replay
  • 不再让 WAL 承担所有长距离恢复:
    • 长间隙恢复转向 checkpoint/snapshot base + tail replay

所以 V2 的性能论点应该是:

  • 健康 steady-state 应该尽量接近 V1.5
  • 退化与恢复路径会更干净
  • 短间隙恢复会比 rebuild 更便宜
  • 长间隙恢复不再逼迫系统支付无上限的 WAL retention 税

这比“V2 天然更快”要可信得多。

4.5 为什么仍然选择 WAL

之所以还继续走 WAL,是因为它仍然是解决这个同步问题最有力的基础:

  • 显式顺序
  • 显式历史
  • 显式 committed prefix
  • 显式短间隙 replay
  • 显式 failover reasoning

只有当设计把以下概念混淆时,WAL 才会变得危险:

  • 本地写入接受
  • replica durable progress
  • committed boundary
  • recoverable retained history

V2 的存在,正是为了不再混淆这些东西。

5. 与市场和论文路线的比较

选择 V2 这条路线,并不是因为别的 vendor 都错了,而是因为他们解决的是不同问题,也承担了不同复杂度。

Ceph / RBD 路线

Ceph/RBD 避开了这种 per-volume replicated WAL 形态。

它获得的是:

  • 对象存储深度一体化
  • 成熟的 placement 与 recovery 体系
  • 更强的集群级分布能力

但代价是:

  • 系统层次更多
  • object-store / peering 复杂度更重
  • 运维与概念模型更重

所以这不是“更简单”,而是把复杂度迁移到了别处。

sw-block 而言,当前选择是:

  • 保持更窄的软件块服务模型
  • 用更显式的 per-volume correctness 来换取更可控的复杂度

PolarFS / ParallelRaft 路线

这类系统探索更激进的顺序与并行策略:

  • conflict-aware 或乱序并行
  • 更深的日志并行
  • 更复杂的 apply / replay 机制

它们在未来仍然值得借鉴:

  • LBA conflict reasoning
  • replay 成本与恢复成本
  • flusher 并行优化

但它们也明显扩大了正确性边界。

在当前阶段,项目不应该在还没彻底证明严格顺序模型之前,就过早买入这类复杂度。

AWS 链式复制 / EBS 类经验

链式复制之类的路线吸引人,是因为它们能解决真实问题:

  • Primary NIC 压力
  • forward 拓扑
  • RF=3 时更好的扩展性

这是后续较有希望借鉴的方向。

但它会改变:

  • 延迟画像
  • 失败处理方式
  • barrier 语义
  • 运维拓扑

所以它属于更后面的架构阶段,而不是当前 V2 核心证明。

当前的真实选择

项目当前选择的是:

  • 更窄的软件优先 block 设计
  • 明确的 per-volume correctness
  • 在性能英雄主义之前先把逻辑讲清
  • 在功能扩张之前先建立验证闭环

这不是保守,而是为了让这个 block 产品未来真的值得信任。

6. 为什么这条方向适合 SeaweedFS 与未来独立 sw-block

sw-block 起步于 SeaweedFS,但 V2 已经在按下一代独立 block service 的方向成形。

这意味着架构上要同时保留两类东西:

需要保持兼容的部分

  • placement / topology 这些概念
  • 可解释的 control-plane contract
  • 与 SeaweedFS 生态的运维连续性

应该更 block-specific 的部分

  • replication correctness
  • recovery ownership
  • recoverability classification
  • block 特有的 test / evidence 体系

因此当前方向不是“继续把 V2 当成 weed 里的一个 patch”,而是:

  • 以 SeaweedFS 作为经验与生态基础
  • 同时把 V2 逐步塑造成真正独立的块服务架构

7. 系统化验证方法

当前方向之所以合理,另一个重要原因是验证方法本身已经系统化。

项目不再依赖:

  • 先实现
  • 再观察
  • 出 bug 再修

而是依赖如下层次:

  • contract / invariants
  • scenario backlog
  • simulator
  • timer/race simulator
  • standalone prototype
  • real engine test runner
flowchart TD
    contract[ContractAndInvariants]
    scenarios[ScenarioBacklog]
    distsim[distsim]
    eventsim[eventsim]
    prototype[enginev2Prototype]
    runner[RealTestRunner]
    confidence[SystemAndProductConfidence]

    contract --> scenarios
    scenarios --> distsim
    scenarios --> eventsim
    distsim --> prototype
    eventsim --> prototype
    prototype --> runner
    runner --> confidence

这对于一个高风险块存储算法是非常正确的结构:

  • simulation 用来证明协议逻辑
  • prototype 用来证明执行语义
  • 真实 runner 用来证明系统与产品行为

8. Simulation 系统证明什么

simulation 系统的目标是回答:

  • 应该发生什么
  • 绝不能发生什么
  • 为什么旧设计会失败
  • 为什么 V2 更好

distsim

distsim 是主协议仿真器,主要用于:

  • 协议正确性
  • 状态迁移
  • stale authority fencing
  • promotion / lineage safety
  • catch-up vs rebuild
  • changed-address restart
  • candidate safety
  • reference-state checking

eventsim

eventsim 是时间 / race 层,主要用于:

  • barrier timeout
  • catch-up timeout
  • reservation timeout
  • 同 tick / 延迟事件顺序
  • stale timeout 的影响

simulation 擅长证明什么

它特别擅长证明:

  • stale traffic rejection
  • recovery boundary 的显式性
  • timeout/race 语义
  • committed prefix 下的 failover 正确性
  • 旧 authority 不能修改新 lineage

simulation 不证明什么

它不证明:

  • 真实 TCP 行为
  • 真实 OS 调度
  • 磁盘时序
  • 真正的 WALShipper 集成
  • iSCSI / NVMe 前端的真实行为

因此 simulation 不是全部真相。

它是 算法 / 协议真相层

9. 真实 test runner 证明什么

learn/projects/sw-block/test/ 下的真实 test runner 是系统与产品验证层。

它不只是 QA 工具,而是设计是否可信的重要组成部分。

它覆盖什么

当前 runner 与周边测试体系已经覆盖:

  • unit
  • component
  • integration
  • distributed scenario
  • 真实硬件 workflow

而且环境已经包含:

  • 真实节点
  • 真实 block target
  • 真实 fault injection
  • benchmark 与结果采集
  • run bundle 与 scenario traceability

为什么它重要

它帮助我们判断:

  • 实际引擎是否按设计运行
  • 产品在真实 restart / failover / rejoin 场景下是否可靠
  • operator workflow 是否可信
  • benchmark 结果是不是有效而非偶然

所以 test runner 最好被理解为:

  • implementation truth
  • system truth
  • product truth

而不只是“测试脚本框架”。

10. Simulation 与 test runner 如何系统性推进

理想的反馈闭环是:

  1. V1 / V1.5 出现真实故障
  2. 这些故障被转化为设计要求
  3. 再被提炼为 simulator 场景
  4. simulator 关闭协议歧义
  5. standalone prototype 关闭执行歧义
  6. 真实 test runner 在硬件与分布式环境中验证系统行为
  7. 新故障或新偏差再反哺设计

这就形成了两类互补真相:

  • simulation -> algorithm / protocol correctness
  • test runner -> implementation / system / product correctness

这种分层是健康的,因为它避免了两种常见错误:

  • 只相信设计推导,却没有真实行为
  • 只相信系统测试全绿,却没有真正理解协议本身

11. 当前状态与诚实边界

现在已经比较强的部分

  • V1.5 相比 V1 的恢复能力已经明显增强,并且有真实运行证据
  • V2 的架构清晰度已经明显强于 V1.5
  • simulator 已经有较强的 acceptance 覆盖
  • prototype 已经开始关闭 ownership 与 orchestration 风险
  • 真实 test runner 已经足够大,可以支撑严肃的系统验证

现在还没有完成的部分

  • V2 还不是生产引擎
  • prototype 仍处于早中期
  • historical-data / recovery-boundary prototype 还没有闭合
  • V2 steady-state 性能还没有真实证明
  • V2 还没有真实硬件上的运行验证

所以最准确的话不是:

  • “V2 现在已经在生产上更强”

而是:

  • “V2 是长期更好的架构,但今天还不是更强的已部署引擎”

12. 为什么当前方向是理性的

当前方向之所以理性,是因为它保持了正确的分工:

  • V1.5 继续作为今天的生产线
  • V2 继续作为下一代架构线

这样项目就可以:

  • 在已有可运行系统上继续交付和加固
  • 在不扰动生产线的前提下认真验证更强的架构
  • 用 simulation、prototype 和真实 runner 来决定 V2 是否真能成为下一代引擎

最终的战略规则应当保持不变:

  • 继续研究 WAL,因为现在我们已经有可信的验证框架
  • 继续推进 V2,因为架构证据已经很强
  • 如果 prototype 证明 V2 有结构性缺陷,就先演进到 V2.5,不要急于重实现

结论

如果按当前生产证据选择:

  • 选择 V1.5

如果按长期协议质量选择:

  • 选择 V2

如果问 WAL 是否还值得继续研究:

  • 值得,因为现在项目已经拥有了足够严肃的验证体系,可以负责任地继续推进

这就是当前最合理的技术与战略判断。