Zum Inhalt springen
Deutsch

LeaseMajority

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Defined in: src/cluster/downing/LeaseMajority.ts:72

Split-brain resolver that uses an external Lease to break ties when the cluster splits into equal-sized partitions — the case where membership-only strategies (KeepOldest, KeepReferee, KeepMajority) cannot make a deterministic call.

Algorithm per partition observation (one side of the split):

  1. Run the standard KeepMajority math.
    • Reachable side has strict majority → down the unreachable side.
    • Reachable side is the strict minority → down ourselves (and every reachable peer on this side).
  2. Equal-size partition (or insufficient info) → start lease.acquire(). Return no decision while the acquire is pending so the cluster waits.
  3. When acquire resolves:
    • true → we are the surviving side. Down the unreachable side.
    • false → some other side won. Down our own side.

The decide() interface stays sync (the rest of the resolver pipeline is sync). Async work happens off-band — this strategy is stateful: the first equal-size observation kicks off the acquire; subsequent ticks read the cached result.

Lease unavailable (network problem reaching the K8s API): acquire() rejects → strategy stays in pending state and returns an empty decision. Better to wait than to risk both sides surviving.

Slow / hung acquire (#142 split-brain hardening)

If lease.acquire() hasn’t resolved by acquireTimeoutMs, the defence-in-depth logic kicks in:

  • Epoch invalidation — every kickoff captures a monotonic acquireEpoch. The timeout-recovery bumps the epoch, so a late-arriving result from the timed-out attempt is dropped (it can’t write a stale decision).
  • Release-on-abandon — we fire-and-forget lease.release() to undo any acquire that may have succeeded on the wire after we gave up locally. Without this, an acquire that timed out on the client but succeeded on the server leaves the lease record claimed without anyone observing the win — a classic stale-token split-brain vector.
  • Fail-safe on release failure — if the abandoning release itself rejects, the lease state is now ambiguous (we may or may not hold it; we can’t tell). The strategy enters fail-safe: every subsequent decide() for the same partition view returns an empty decision, refusing to claim majority until the partition heals (which resets the fail-safe flag).

Fencing tokens (optional)

If the underlying Lease implements acquireWithToken() (K8s Lease’s resourceVersion, Redis SETNX with counter, etc.), the strategy uses it instead of plain acquire(). The token isn’t inspected at decide-time — the local epoch is the source of truth for “is this result still valid?” — but having the token means tighter integration with the underlying lease’s native fencing primitive (e.g. release-with-token semantics, when future work adds them).

new LeaseMajority(options): LeaseMajority

Defined in: src/cluster/downing/LeaseMajority.ts:106

LeaseMajorityOptions

LeaseMajority

decide(view): DowningDecision

Defined in: src/cluster/downing/LeaseMajority.ts:111

Return addresses to forcibly down. The empty set means “not yet — wait for stability or more heartbeats”.

ClusterPartitionView

DowningDecision

DowningProvider.decide