Files
seaweedfs/sw-block/design/v2-algorithm-overview.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

21 KiB

V2 Algorithm Overview

Date: 2026-03-27 Status: strategic design overview Audience: CEO / owner / technical leadership

Purpose

This document explains the current V2 direction for sw-block:

  • what V2 is trying to solve
  • why V1 and V1.5 are not enough as the long-term architecture
  • why a WAL-based design is still worth pursuing
  • how V2 compares with major market and paper directions
  • how simulation and the real test runner systematically build confidence

This is not a phase report and not a production-commitment document.

It is the high-level technical rationale for the V2 line.

Relationship To Other Documents

Document Role
v1-v15-v2-comparison.md Detailed comparison of the three lines
v2-acceptance-criteria.md Protocol validation bar
v2_scenarios.md Scenario backlog and simulator mapping
v2-open-questions.md Remaining algorithmic questions
protocol-development-process.md Method for protocol work
learn/projects/sw-block/algorithm_overview.md Current V1/V1.5 system review
learn/projects/sw-block/design/algorithm_survey.md Paper and vendor survey
learn/projects/sw-block/test/README.md Real test runner overview
learn/projects/sw-block/test/test-platform-review.md Test platform maturity and standalone direction

1. Executive Summary

The current judgment is:

  • V1 proved that the basic WAL-based replicated block model can work.
  • V1.5 materially improved real recovery behavior and now has stronger operational evidence on real hardware.
  • V2 exists because the next correctness problems should not be solved by incremental local fixes. They should be made explicit in the protocol itself.

The central V2 idea is simple:

  • short-gap recovery should be explicit
  • stale authority should be explicitly fenced
  • catch-up vs rebuild should be an explicit decision
  • recovery ownership should be a protocol object, not an implementation accident

V2 is not yet a production engine. But it is already the stronger architectural direction.

The correct strategic posture today is:

  • continue V1.5 as the production line
  • continue V2 as the long-term architecture line
  • continue WAL investigation because we now have a serious validation framework
  • if prototype evidence later shows a structural flaw, evolve to V2.5 before heavy implementation

2. The Real Problem V2 Tries To Solve

At the frontend, a block service looks simple:

  • write
  • flush / sync
  • failover
  • recovery

But the real difficulty is not the frontend verb set. The real difficulty is the asynchronous distributed boundary between:

  • local WAL append on the primary
  • durable progress on replicas
  • client-visible commit / sync truth
  • failover and promotion safety
  • recovery after lag, restart, endpoint change, or timeout

This is the root reason V2 exists.

The project has already learned that correctness problems in block storage do not usually come from the happy path. They come from:

  • a replica going briefly down and coming back
  • a replica coming back on a new address
  • a delayed stale barrier or stale reconnect result
  • a lagging node that is almost, but not quite, recoverable
  • a failover decision made on insufficient lineage information

V2 is the attempt to make those cases first-class protocol behavior instead of post-hoc patching.

3. Why V1 And V1.5 Are Not Enough

This overview does not need a long retelling of V1 and V1.5.

What matters is their architectural limit.

What V1 got right

V1 proved the basic shape:

  • ordered WAL
  • primary-replica replication
  • extent-backed storage
  • epoch and lease as the first fencing model

Why V1 is not enough

Its main shortcomings were:

  • short-gap recovery was too weak and too implicit
  • lagging replicas too easily fell into rebuild or long degraded states
  • changed-address restart was fragile
  • stale authority and stale results were not modeled as first-class protocol objects
  • the system did not cleanly separate:
    • current WAL head
    • committed prefix
    • recoverable retained range
    • stale or divergent replica tail

Why V1.5 is still not enough

V1.5 fixed several real operational problems:

  • retained-WAL catch-up
  • same-address reconnect
  • sync_all correctness on real tests
  • rebuild fallback after unrecoverable gap
  • control-plane refresh after changed-address restart

Those fixes matter, and they are why V1.5 is the stronger production line today.

But V1.5 is still not the long-term architecture because its recovery model remains too incremental:

  • reconnect logic is still layered onto an older shipper model
  • recovery ownership was discovered as a bug class before it became a protocol object
  • catch-up vs rebuild became clearer, but still not clean enough as a top-level protocol contract
  • the system still looks too much like "repair V1" rather than "define the next replication model"

What V2 changes

V2 is not trying to invent a completely different storage model.

It is trying to make the critical parts explicit:

  • recovery ownership
  • lineage-safe recovery boundary
  • catch-up vs rebuild classification
  • per-replica sender authority
  • stale-result rejection
  • explicit recovery orchestration

So the correct comparison is still:

  • V1.5 is stronger operationally today
  • V2 is stronger architecturally today

That is not a contradiction. It is the right split between a current production line and the next architecture line.

flowchart TD
    V1[V1]
    V15[V1_5]
    V2[V2]
    realFailures[RealFailures]
    realTests[RealHardwareEvidence]
    simAndProto[SimulationAndPrototype]

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

4. How V2 Solves WAL And Extent Synchronization

The core V2 question is not simply "do we keep WAL?"

The real question is:

how do WAL and extent stay synchronized across primary and replica while preserving both stability and performance?

This is the center of the V2 design.

4.1 The basic separation of roles

V2 treats the storage path as two different but coordinated layers:

  • WAL is the ordered truth for recent history
  • extent is the stable materialized image

WAL is used for:

  • strict write ordering
  • local crash recovery
  • short-gap replica catch-up
  • durable progress accounting through LSN

Extent is used for:

  • stable read image
  • long-lived storage
  • checkpoint and base-image creation
  • long-gap recovery only through a real checkpoint/snapshot base, not through guessing from the current live extent

This separation is the first stability rule:

  • do not ask current extent to behave like historical state
  • do not ask WAL to be the only long-range recovery mechanism forever

4.2 Primary-replica synchronization model

The intended V2 steady-state model is:

  1. primary allocates monotonic LSN
  2. primary appends ordered WAL locally
  3. primary enqueues the record to per-replica sender loops
  4. replicas receive in order and advance explicit progress
  5. barrier/sync uses durable replica progress, not optimistic send progress
  6. flusher later materializes WAL-backed dirty state into extent

The local WAL-to-extent lifecycle can be understood as:

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

    note right of WalAppended
        Ordered local WAL exists
        and defines the write LSN
    end note

    note right of ReplicaDurable
        Replica durable progress
        is now explicit
    end note

    note right of ExtentMaterialized
        Flusher moves stable data
        from WAL-backed dirty state
        into extent
    end note

The critical synchronization rule is:

  • client-visible sync truth must follow durable replica progress
  • not local send progress
  • not local WAL head
  • not "replica probably received it"

This is why V2 uses a lineage-safe recovery target such as CommittedLSN instead of a looser notion like "current primary head."

4.2.1 Sync mode and result model

V2 also makes the sync-result logic more explicit.

  • best_effort should succeed after the primary has reached its local durability point, even if replicas are degraded.
  • sync_all should succeed only when all required replicas are durable through the target boundary.
  • sync_quorum should succeed only when a true durable quorum exists through the target boundary.

This decision path can be presented as:

flowchart TD
    writeReq[WriteAndSyncRequest]
    localDurable[PrimaryLocalDurable]
    barrierEval[EvaluateReplicaDurableProgress]
    bestEffortAck[best_effortAck]
    syncAllAck[sync_allAck]
    syncQuorumAck[sync_quorumAck]
    rejectOrBlock[RejectOrBlock]

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

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

The key point is that sync success is no longer inferred from send progress or socket health. It is derived from explicit durable progress at the right safety boundary.

4.3 Why this should be stable

This model is designed to be stable because the dangerous ambiguities are separated:

  • write ordering is carried by WAL and LSN
  • durability truth is carried by barrier / flushed progress
  • recovery ownership is carried by sender + recovery attempt identity
  • catch-up vs rebuild is an explicit classification, not an accidental timeout side effect
  • promotion safety depends on committed prefix and lineage, not on whichever node looks newest

In other words, V2 stability comes from reducing hidden coupling.

The design tries to remove cases where one piece of state silently stands in for another.

4.4 Why this can still be high-performance

The performance argument is not that V2 is magically faster in all cases.

The argument is narrower and more realistic:

  • keep the primary write path simple:
    • ordered local WAL append
    • enqueue to per-replica sender loops
    • no heavy inline recovery logic in foreground writes
  • keep most complexity off the healthy hot path:
    • sender ownership
    • reconnect classification
    • catch-up / rebuild decisions
    • timeout and stale-result fencing live mostly in recovery/control paths
  • use WAL for what it is good at:
    • recent ordered delta
    • short-gap replay
  • stop using WAL as the answer to every lag problem:
    • long-gap recovery should move toward checkpoint/snapshot base plus tail replay

So the V2 performance thesis is:

  • healthy steady-state should remain close to V1.5
  • degraded/recovery behavior should become much cleaner
  • short-gap recovery should be cheaper than rebuild
  • long-gap recovery should stop forcing an unbounded WAL-retention tax

That is a much stronger and more believable claim than saying "V2 will just be faster."

4.5 Why WAL is still worth choosing

The reason to keep the WAL-based direction is that it gives the best foundation for this exact synchronization problem:

  • explicit order
  • explicit history
  • explicit committed prefix
  • explicit short-gap replay
  • explicit failover reasoning

WAL is risky only if the design blurs:

  • local write acceptance
  • replica durable progress
  • committed boundary
  • recoverable retained history

V2 exists precisely to stop blurring those things.

So the current project position is:

  • WAL is not automatically safe
  • but WAL is still the most promising base for this block service
  • because the project now has enough real evidence, simulator coverage, and prototype work to investigate it rigorously

5. Comparison With Market And Papers

The current V2 direction is not chosen because other vendors are wrong. It is chosen because other directions solve different problems and carry different costs.

Ceph / RBD style systems

Ceph-style block systems avoid this exact per-volume replicated WAL shape. They gain:

  • deep integration with object-backed distributed storage
  • mature placement and recovery machinery
  • strong cluster-scale distribution logic

But they pay elsewhere:

  • more system layers
  • more object-store and peering complexity
  • a heavier operational and conceptual model

This is not a free simplification. It is a different complexity trade.

For sw-block, the design choice is to keep a narrower software block service with more explicit per-volume replication semantics instead of inheriting the full distributed object-backed block complexity stack.

PolarFS / ParallelRaft style work

These systems explore more aggressive ordering and apply strategies:

  • out-of-order or conflict-aware work
  • deeper parallelism
  • more sophisticated log handling

They are valuable references, especially for:

  • LBA conflict reasoning
  • recovery and replay cost thinking
  • future flusher parallelization ideas

But they also introduce a much heavier correctness surface.

The project does not currently want to buy that complexity before fully proving the simpler strict-order path.

AWS chain replication / EBS-style lessons

Chain replication and related work are attractive because they address real bandwidth and recovery concerns:

  • Primary NIC pressure
  • forwarding topology
  • cleaner scaling for RF=3

This is one of the more plausible borrowable directions later.

But it changes:

  • latency profile
  • failure handling
  • barrier semantics
  • operational topology

So it belongs to a later architecture stage, not to the current V2 core proof.

The actual strategic choice

The project is deliberately choosing:

  • a narrower software-first block design
  • explicit per-volume correctness
  • strict reasoning before performance heroics
  • validation before feature expansion

That is not conservatism for its own sake. It is how to build a block product that can later be trusted.

6. Why This Direction Fits SeaweedFS And Future Standalone sw-block

sw-block started inside SeaweedFS, but V2 is already being shaped as the next standalone block service line.

That means the architecture should preserve two things at once:

What should remain compatible

  • placement and topology concepts where they remain useful
  • explainable control-plane contracts
  • operational continuity with the SeaweedFS ecosystem

What should become more block-specific

  • replication correctness
  • recovery ownership
  • recoverability classification
  • block-specific test and evidence story

So the current direction is:

  • use SeaweedFS as the practical ecosystem and experience base
  • but shape V2 as a true block-service architecture, not as a minor sub-feature of weed/

This is why the V2 line belongs under sw-block/ rather than as a direct patch path inside the existing production tree.

7. The Systematic Validation Method

The second major reason the current direction is rational is the validation method.

The project is no longer relying on:

  • implement first
  • discover behavior later
  • patch after failure

Instead, the intended ladder is:

  • contract and 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

This is the right shape for a risky block-storage algorithm:

  • simulation for protocol truth
  • prototype for executable truth
  • real runner for product/system truth

8. What The Simulation System Proves

The simulation system exists to answer:

  • what should happen
  • what must never happen
  • which V1/V1.5 shapes fail
  • why the V2 shape is better

distsim

distsim is the main protocol simulator.

It is used for:

  • protocol correctness
  • state transitions
  • stale authority fencing
  • promotion and lineage safety
  • catch-up vs rebuild
  • changed-address restart
  • candidate safety
  • reference-state checking

eventsim

eventsim is the timing/race layer.

It is used for:

  • barrier timeout behavior
  • catch-up timeout behavior
  • reservation timeout behavior
  • same-tick and delayed event ordering
  • stale timeout effects

What the simulator is good at

It is especially strong for proving:

  • stale traffic rejection
  • explicit recovery boundaries
  • timeout/race semantics
  • failover correctness at committed prefix
  • why old authority must not mutate current lineage

What the simulator does not prove

It does not prove:

  • real TCP behavior
  • real OS scheduling behavior
  • disk timing
  • real WALShipper integration
  • real frontend behavior under iSCSI or NVMe

So the simulator is not the whole truth.

It is the algorithm/protocol truth layer.

9. What The Real Test Runner Proves

The real test runner under learn/projects/sw-block/test/ is the system and product validation layer.

It is not merely QA support. It is a core part of whether the design can be trusted.

What it covers

The runner and surrounding test system already span:

  • unit tests
  • component tests
  • integration tests
  • distributed scenarios
  • real hardware workflows

The environment already includes:

  • real nodes
  • real block targets
  • real fault injection
  • benchmark and result capture
  • run bundles and scenario traceability

Why it matters

The runner is what tells us whether:

  • the implemented engine behaves like the design says
  • the product works under real restart/failover/rejoin conditions
  • the operator workflows are credible
  • benchmark claims are real rather than accidental

This is why the runner is best thought of as:

  • implementation truth
  • system truth
  • product truth

not just test automation.

10. How Simulation And Test Runner Progress Systematically

The intended feedback loop is:

  1. V1/V1.5 real failures happen
  2. those failures are turned into design requirements
  3. scenarios are distilled for simulator use
  4. the simulator closes protocol ambiguity
  5. the standalone prototype closes execution ambiguity
  6. the real test runner validates system behavior on real environments
  7. new failures or mismatches feed back into design again

This gives the project two different but complementary truths:

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

That separation is healthy.

It prevents two common mistakes:

  • trusting design without real behavior
  • trusting green system tests without understanding the protocol deeply enough

11. Current Status And Honest Limits

What is already strong

  • V1.5 has materially better recovery behavior than V1 and stronger operational evidence
  • V2 has stronger architectural structure than V1.5
  • the simulator has serious acceptance coverage
  • the prototype line has already started closing ownership and orchestration risk
  • the real test runner is large enough to support serious system validation

What is not yet done

  • V2 is not a production engine
  • prototype work is still in early-to-mid stages
  • historical-data / recovery-boundary prototype work is not complete
  • steady-state performance of V2 is not yet proven
  • real hardware validation of V2 does not yet exist

So the correct statement is not:

  • "V2 is already better in production"

The correct statement is:

  • "V2 is the better long-term architecture, but not yet the stronger deployed engine"

12. Why The Current Direction Is Rational

The current direction is rational because it keeps the right split:

  • V1.5 continues as the production line today
  • V2 continues as the next architecture line

This lets the project:

  • keep shipping and hardening what already works
  • explore the better architecture without destabilizing the current engine
  • use simulation, prototype work, and the real runner to decide whether V2 should become the next real engine

The final strategic rule should remain:

  • continue WAL investigation because the project now has a credible validation framework
  • continue V2 because the architectural evidence is strong
  • if prototype evidence later reveals a structural flaw, redesign to V2.5 before heavy implementation

That is the disciplined path for a block-storage algorithm.

Bottom Line

If choosing based on current production proof:

  • use V1.5

If choosing based on long-term protocol quality:

  • choose V2

If choosing based on whether WAL should still be investigated:

  • yes, because the project now has the right validation stack to investigate it responsibly

That is the current strategic answer.