1 Punkte von GN⁺ 2025-12-09 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Jepsen validierte die Robustheit und Konsistenz des verteilten Messaging-Systems NATS JetStream unter verschiedenen Fehlerbedingungen
  • Die Testergebnisse zeigten bei Dateibeschädigung (.blk, Snapshot) und Power-Failure-Simulationen Datenverlust und Split-Brain-Zustände
  • JetStream führt standardmäßig fsync nur alle 2 Minuten aus, sodass zuletzt bestätigte Nachrichten möglicherweise nicht auf der Festplatte gespeichert sind
  • Ein einzelner OS-Crash eines Nodes kann bereits zu Datenverlust und Replikatsinkonsistenz führen
  • Jepsen empfiehlt für NATS, die Standardeinstellung auf fsync=always zu ändern oder die Datenverlustgefahr explizit in der Dokumentation zu kennzeichnen

1. Hintergrund

  • NATS ist ein beliebtes Streaming-System, das Nachrichten als Stream publiziert und abonniert
    • JetStream verwendet den Raft-Konsensalgorithmus, repliziert Daten und garantiert at-least-once-Zustellung
  • JetStream behauptet in der Dokumentation, Linearizable-Konsistenz und Always-Available-Verfügbarkeit zu bieten, doch laut CAP-Theorem können diese beiden Anforderungen nicht gleichzeitig erfüllt werden
  • Laut NATS-Dokumentation kann ein 3-Knoten-Stream 1 und ein 5-Knoten-Stream 2 Serverausfälle tolerieren
  • Eine Nachricht gilt als „erfolgreich gespeichert“, sobald der Server die publish-Anfrage acknowledged hat
  • Zur Wahrung der Datenkonsistenz wird ein Quorum von mehr als der Hälfte der Nodes benötigt; in einem 5-Knoten-Cluster sind mindestens 3 Nodes erforderlich, damit neue Nachrichten gespeichert werden können

2. Testdesign

  • Jepsen führte die Tests mit dem JNATS 2.24.0-Client und in einer Debian-12-LXC-Container-Umgebung durch
    • Einige Tests nutzten in der Antithesis-Umgebung das offizielle NATS-Docker-Image
  • Es wurde ein einzelner JetStream-Stream (Replikationsfaktor 5) aufgebaut und Prozessabbruch, Absturz, Netzwerktrennung, Paketverlust, Dateibeschädigung u. a. injiziert
  • Mit dem LazyFS-Dateisystem wurde eine Power-Failure-Simulation durchgeführt, die nicht fsync-gesicherte Schreibvorgänge verliert
  • Jeder Prozess veröffentlichte eindeutige Nachrichten; nach Testende wurde auf allen Nodes geprüft, ob acknowledgierte Nachrichten vorhanden sind
  • Wenn Nachrichten nur auf einigen Nodes vorhanden sind, wird das als Divergence (Replikationsabweichung) klassifiziert

3. Hauptbefunde

3.1 Vollständiger Datenverlust in NATS 2.10.22 (#6888)

  • Es wurde ein vollständiger Verlust eines gesamten JetStream-Streams durch einen einfachen Prozessabsturz festgestellt
  • Nach dem Fehler "No matching streams for subject" gab es über Stunden keine Wiederherstellung
  • Ursache war Leader-Snapshot-Inversion, Raft-Statuslöschung u. a.; behoben in Version 2.10.23

3.2 Datenverlust bei Beschädigung von .blk-Dateien (#7549)

  • Bei einem einzigen Bitfehler oder Trunkierung in der JetStream-.blk-Datei ging eine große Anzahl bestätigter Schreibvorgänge verloren
    • Beispiel: 679.153 von 1.367.069 gingen verloren
  • Auch bei Beschädigung nur einzelner Nodes kam es zu massivem Datenverlust und Split-Brain
    • Beispiel: Bis zu 78 % Nachrichtenverlust auf den Nodes n1, n3, n5
  • NATS untersucht den Fehler derzeit noch

3.3 Gesamtdatenverlust bei Snapshot-Dateibeschädigung (#7556)

  • Wird die Snapshot-Datei unter data/jetstream/$SYS/_js_/ beschädigt, stuft der Node den Stream als orphaned ein und löscht sämtliche Daten
  • Bereits die Beschädigung weniger Nodes verhindert das Quorum und macht den Stream dauerhaft unbenutzbar
  • Beispiel: Beschädigung der Nodes n3, n5 führte dazu, dass n3 zum Leader gewählt wurde und jepsen-stream vollständig gelöscht wurde
  • Jepsen weist darauf hin, dass bei der Leader-Wahl ein beschädigter Node zum Leader werden kann

3.4 Datenverlust durch die Standard-fsync-Einstellung (#7564)

  • JetStream führt standardmäßig nur alle 2 Minuten fsync aus, bestätigt Nachrichten jedoch sofort
    • Dadurch bleiben kürzlich bestätigte Nachrichten ungespeichert auf der Platte
  • Bei Stromausfall oder Kernel-Crash gehen innerhalb von Sekundenbereichs bestätigte Nachrichten verloren
    • Beispiel: 131.418 von 930.005 gingen verloren
  • Auch bei aufeinanderfolgenden Ausfällen einzelner Nodes ist ein vollständiges Löschen des Streams möglich
  • Das Verhalten wird in der Dokumentation kaum erwähnt
  • Jepsen empfiehlt die Umstellung auf fsync=always oder einen ausdrücklichen Warnhinweis zum Datenverlust-Risiko

3.5 Split-Brain durch einen einzelnen OS-Crash (#7567)

  • Ein Stromausfall oder Kernel-Crash eines einzelnen Nodes kann bereits zu Datenverlust und Replikatsinkonsistenz führen
  • In einem Leader-Follower-Setup kann es passieren, dass Knoten einen Write nur im Speicher committen und bestätigen, aber bei einem Ausfall danach
    verlieren mehrere Nodes diesen Write und arbeiten in einem neuen Zustand weiter
  • In den Tests trat nach einem einzelnen Stromausfall ein anhaltendes Split-Brain auf
    • Pro Node wurden unterschiedliche Intervalle fehlender acknowledged Nachrichten beobachtet
  • Jepsen verweist auf ähnliche Fälle bei Kafka und betont, dass dasselbe Risiko auch in Raft-basierten Systemen existiert

4. Diskussion und Fazit

  • Das Problem des vollständigen Datenverlusts in 2.10.22 wurde in 2.10.23 behoben
  • In 2.12.1 treten weiterhin Datenverlust und Split-Brain durch Dateibeschädigung und OS-Crashs auf
  • Bei .blk- und Snapshot-Dateibeschädigungen fehlen auf einzelnen Nodes Nachrichten oder der gesamte Stream wird gelöscht
  • Durch den langen Standard-fsync-Intervall besteht bei gleichzeitigen Ausfällen mehrerer Nodes weiterhin das Risiko, dass acknowledged Daten verloren gehen
  • Jepsen empfiehlt fsync=always oder eine klare Risikodokumentation in den Unterlagen
  • Die Aussage „Always Available“ von JetStream ist im Rahmen des CAP-Theorems unmöglich, die Dokumentation muss angepasst werden
  • Jepsen betont, dass ein Bug nachgewiesen werden kann, das Fehlen von Sicherheit jedoch nicht beweisbar ist

4.1 Rolle von LazyFS

  • Mit LazyFS wurden die Verluste nicht fsync-gesicherter Schreibvorgänge simuliert
  • Bei Stromausfall können so verschiedene Storage-Fehler, darunter partielle Schreibfehler (torn writes), nachgestellt werden
  • In der zugehörigen Arbeit When Amnesia Strikes (VLDB 2024) werden ähnliche Bugs auch bei PostgreSQL, Redis und ZooKeeper berichtet

4.2 Nächste Schritte

  • Der Verlust auf Single-Consumer-Ebene, die Reihenfolge von Nachrichten sowie die Prüfung von Linearizable/Serializable-Garantien wurden nicht durchgeführt
  • Die exactly-once-Zustellung wird ebenfalls als Thema für künftige Untersuchungen genannt
  • Bei Node-Hinzufügung und -Entfernung wurden Dokumentationsfehler sowie das Fehlen von Pflicht-Health-Check-Schritten festgestellt (#7545)
  • Ein sicheres Verfahren zur Änderung der Cluster-Konfiguration ist weiterhin unklar

Noch keine Kommentare.

Noch keine Kommentare.