Rebalance
Wenn sich die Mitgliedschaft des Clusters ändert — ein Node tritt bei oder geht — müssen Shards wandern, um die Last verteilt zu halten. Der Koordinator treibt den Prozess: er wählt Shards aus, die umziehen, sagt der Quellregion, sie soll übergeben, und wartet auf Bestätigung, bevor er neu allokiert.
Das ist absichtlich konservativ — gepufferte Nachrichten
warten auf HandOffComplete, bevor sie an den neuen Besitzer
weitergeleitet werden, damit nichts an einer halb-verschobenen
Entity vorbei rast.
Was Rebalance auslöst
Abschnitt betitelt „Was Rebalance auslöst“Zwei Pfade:
- Mitgliedschaftsgetrieben —
MemberUp(ein neuer Node),MemberRemoved(ein gehender Node) oder jeder Cluster-Übergang, der die Kandidatenmenge ändert. Der Koordinator führt die Allokationsstrategie für jeden besessenen Shard erneut aus. - Strategiegetrieben — alle
rebalanceIntervalMs(Default 2 s) fragt der Koordinator die Allokationsstrategie nach ihren Rebalance-Empfehlungen.LeastShardAllocationStrategygibt Shards zum Drainen von beschäftigten Nodes zurück;HashAllocationStrategygibt Shards zurück, deren Hash-Ziel gewandert ist.
Beide speisen denselben Handoff-Mechanismus.
Die Handoff-Sequenz
Abschnitt betitelt „Die Handoff-Sequenz“Wenn der Koordinator entscheidet, dass Shard X von Node A zu
Node B wandern soll:
HandOff(X)wird an die Region von Node A geschickt.- Die Region von Node A markiert Shard
Xalshanding-off. Sie empfängt weiterhin Nachrichten für Entities inX, aber puffert sie, statt sie an Entity-Actors weiterzuleiten. - Jede Entity in
Xerhält das Stop-Signal des Frameworks. Sie führenpostStopaus, persistieren etwaigen Final-State und sterben. - Sobald alle Entities in
Xweg sind, schickt Node AHandOffComplete(X)an den Koordinator. - Der Koordinator führt
allocate(X, ...)aus, um ein neues Zuhause zu wählen. Nehmen wir an, er wählt Node B. - Der Koordinator veröffentlicht den neuen Besitzer per Gossip. Gepufferte Nachrichten auf Node A beginnen, an die Region von Node B weiterzuleiten.
- Die Region von Node B empfängt Nachrichten für Entities in
Xund spawnt Entities bei Bedarf (genau wie bei der Erst-Allokation).
Das Ganze dauert üblicherweise sub-Sekunde bis ein paar
Sekunden, abhängig davon, wie viele Entities im Shard sind und
wie lang ihre postStop-Arbeit dauert.
Konfiguration
Abschnitt betitelt „Konfiguration“sharding.start({ // ... rebalanceIntervalMs: 2_000, // Strategie-getriebenes Rebalance alle 2s handOffTimeoutMs: 10_000, // nach 10s aufgeben + zwangsweise neu allokieren});| Knopf | Default | Was |
|---|---|---|
rebalanceIntervalMs | 2000 | Wie oft die Strategie nach Rebalance-Empfehlungen befragt wird. |
handOffTimeoutMs | 10_000 | Wenn die Quellregion nicht innerhalb dieses Fensters HandOffComplete sendet, gibt der Koordinator das Warten auf und allokiert zwangsweise neu. |
Was gepufferte Nachrichten bedeuten
Abschnitt betitelt „Was gepufferte Nachrichten bedeuten“Während Shard X handing-off ist:
- Nachrichten an Entities in
Xkommen bei Node A an. - Die Region von Node A puffert sie — leitet sie nicht an die (jetzt gestoppten) Entity-Actors weiter.
- Sobald der Handoff abgeschlossen ist und
Xeinen neuen Besitzer hat, leiten gepufferte Nachrichten an die neue Region weiter. - Die neue Region spawnt Entities und verarbeitet die Nachrichten in Reihenfolge.
Das bedeutet, dass eine während des Handoffs gesendete Nachricht verzögert ist, nicht verloren. Die Kosten: Latenzspitzen während Rebalance-Fenstern.
Wenn Entities State haben
Abschnitt betitelt „Wenn Entities State haben“Für persistente Entities (PersistentActor):
postStopauf der Quellseite schließt etwaiges ausstehendes Persist ab.- Die neue Entity-Instanz auf dem Ziel spielt das Journal beim Start ab.
- Die gepufferte Nachricht kommt bei einer vollständig wiederhergestellten Entity an.
Für nicht-persistente Entities ist der State zwischen Inkarnationen verloren — der Rebalance entspricht einem Restart, bei dem die gepufferte Nachricht als erstes Kommando wirkt.
Wenn State über Rebalance hinweg zählt, nutze Persistenz. Das ist nicht optional.
Zwangsweise Neuallokation
Abschnitt betitelt „Zwangsweise Neuallokation“Wenn HandOffComplete nicht innerhalb von handOffTimeoutMs
eintrifft:
- Der Koordinator loggt eine Warnung (“handoff timed out”).
- Er allokiert den Shard zwangsweise auf seinen neuen Besitzer.
- Gepufferte Nachrichten leiten weiter, als wäre der Handoff normal abgeschlossen.
- Die alten Entities sind möglicherweise noch am Leben auf Node A — sie empfangen auch lokal Nachrichten, was zu Split-Brain-Entities führt, bis die Waisen sterben.
Das ist selten, aber möglich. Ursachen:
- Ein
postStop, das hängt (langsamer Journal-Write, blockierender externer Call). - Eine Netzwerkpartition während des Handoffs.
Abhilfe:
- Halte
postStopkurz und nicht-blockierend. - Tune
handOffTimeoutMsauf deine Worst-Case-Persist-Zeit + Puffer. - Für das Split-Brain-Risiko erwäge eine Lease auf dem Sharding-Koordinator (siehe Sharding mit Lease).
Rebalance vs. Skalierung
Abschnitt betitelt „Rebalance vs. Skalierung“Node hinzugefügt → Koordinator allokiert ihm einige ShardsNode entfernt → Koordinator findet neue Heimaten für seine ShardsNode ↑ in Last → LeastShardAllocationStrategy drainiert Shards wegNode ↓ in Last → kein Rebalance (nur die belastete Richtung löst aus)Rebalance ist Arbeitsabgabe, nicht Arbeitseinwerbung. Ein
leerlaufender Node bekommt aus Sicht von
LeastShardAllocationStrategy neue Shards, sobald sie allokiert
werden, aber er bekommt keine existierenden Shards in sich
verschoben, nur weil er ruhig ist.
Für einen “immer-balanciert”-Effekt starte den Koordinator
periodisch neu (was Allokation von Null neu laufen lässt) — oder
konfiguriere rebalanceThreshold: 1, um auf jedes Ungleichgewicht
zu reagieren.
Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- Sharding-Überblick — das größere Bild.
- Allokationsstrategie — was die neuen Heimaten entscheidet.
- Remember Entities — beeinflusst, was nach Handoff neu gespawnt wird.
- Sharding mit Lease — Split-Brain-Schutz für den Koordinator.