7 Punkte von xguru 2024-08-09 | 1 Kommentare | Auf WhatsApp teilen
  • rqlite ist eine leichtgewichtige Open-Source-Distributed-Relational-Datenbank, die in Go geschrieben ist
  • Sie basiert auf dem Raft-Konsensprotokoll und verwendet SQLite als Storage Engine
  • Die Entwicklung von 9.0 hat begonnen und zielt darauf ab, den Festplattenverbrauch um etwa 50 % zu senken
  • Dieses Ziel soll durch eine High-Level-Neugestaltung des Designs erreicht werden, die die Hauptursache des Festplattenverbrauchs von rqlite beseitigt

Was belegt derzeit hauptsächlich den Speicherplatz?

  • Raft-Log:
    • Ein Log der Änderungen am System
    • Dieses Log ist der Kern des Raft-Konsenssystems
  • Arbeits-SQLite-Datenbank:
    • Die Live-Datenbank, die rqlite zum Bereitstellen von Lese- und Schreibzugriffen verwendet
    • Sobald ein SQLite-Statement erfolgreich im Raft-Log committet wurde, wird es auf die Arbeits-SQLite-Datenbank angewendet
  • Snapshot der Arbeits-SQLite-Datenbank:
    • Um zu verhindern, dass das Raft-Log unbegrenzt wächst, erstellt und speichert das Raft-Subsystem in rqlite periodisch eine Point-in-Time-Kopie der Arbeits-SQLite-Datenbank
    • Diese Kopie wird Snapshot genannt
    • Sobald ein Snapshot erstellt ist, kann rqlite das Raft-Log kürzen
    • Diese als Snapshot gespeicherte Kopie wird von rqlite verwendet, um einen Node beim Neustart wiederherzustellen, oder an andere Nodes übertragen, wenn diese den Zustand eines bestehenden rqlite-Clusters „aufholen“ müssen
    • Snapshot-Erstellung und Log-Kürzung sind Kernkonzepte von Raft-basierten Systemen

High-Level-Design für rqlite 9.0

  • Die zentrale Strategie zur Reduzierung des Festplattenverbrauchs besteht darin, die Notwendigkeit zu entfernen, im Raft-System eine als Snapshot gespeicherte Kopie der Arbeits-SQLite-Datenbank abzulegen
  • Das Raft-Log wird durch Snapshot-Erstellung periodisch gekürzt und wächst ab einem bestimmten Zeitpunkt nicht mehr weiter, die Arbeits-SQLite-Datenbank hingegen wächst weiter, wenn mehr Daten geschrieben werden
  • Und da die Snapshot-Kopie der SQLite-Datenbank fast genauso groß ist wie die Arbeits-SQLite-Datenbank, wächst auch sie entsprechend
  • Wenn diese Snapshot-Kopie also entfernt werden kann, wird rqlite 50 % weniger Festplattenplatz benötigen
  • Allerdings benötigt ein rqlite-Node zu bestimmten Zeitpunkten eine als Snapshot gespeicherte Kopie. Das ist unvermeidlich.
  • Wie kann man also die Kopie weglassen und trotzdem die Anforderungen an Snapshot-Erstellung und Wiederherstellung erfüllen?
  • Um zu verstehen, wie sich eine zusätzliche gespeicherte Kopie im Snapshot-Prozess vermeiden lässt, ist wichtig zu wissen, dass rqlite die zugrunde liegende SQLite-Datenbank im Write-Ahead Log(WAL)-Modus betreibt
  • Im vorgeschlagenen 9.0-Design sind die Datei der Arbeits-SQLite-Datenbank (ohne die zugehörige WAL-Datei) und die als Snapshot gespeicherte Kopie im Raft-System logisch identisch
  • Diese Tatsache kann genutzt werden, um die Notwendigkeit zu beseitigen, im Raft-System eine separate Snapshot-Kopie zu speichern

Neuer Ansatz zur Snapshot-Erstellung

  • Snapshot-Erstellung und WAL-Checkpointing:
    • Zum Zeitpunkt der Snapshot-Erstellung checkpointet rqlite das Write-Ahead Log(WAL) der Arbeits-SQLite-Datenbank
    • Alle nachfolgenden Schreibvorgänge gehen dann in eine neue WAL-Datei, sodass die Haupt-SQLite-Datei ab dem Zeitpunkt der Snapshot-Erstellung unverändert bleibt
    • Dadurch repräsentiert die Haupt-SQLite-Datei bis zum nächsten Snapshot den Point-in-Time-Zustand, den der Raft-Snapshot-Store benötigt
    • Mit diesem Ansatz verwenden normale Lese- und Schreiboperationen die kombinierte SQLite-Datei und WAL-Datei, während die unveränderte Haupt-SQLite-Datei als Datensatz für den Raft-Snapshot-Store dient
    • Es ist keine zusätzliche Kopie mehr nötig!
  • Schreiben einer Referenz in den Snapshot-Store:
    • Anstatt die vollständige SQLite-Datei zu kopieren, schreibt rqlite eine Referenz wie etwa eine Prüfsumme in den Snapshot-Store
    • Diese Referenz kann verwendet werden, um bei Bedarf zu prüfen, ob die Haupt-SQLite-Datei mit dem übereinstimmt, worauf der Snapshot-Store verweist
      • (Diese Prüfung schützt vor Bugs, Betriebsfehlern oder Festplattenbeschädigung, ist aber nicht zwingend erforderlich)
  • Wiederherstellung aus einem Snapshot:
    • Wie erwähnt gehen alle Schreibvorgänge nach dem Snapshot-Prozess in die WAL-Datei, sodass die Haupt-SQLite-Datei bereitsteht, um für den Wiederherstellungsprozess aus einem Snapshot verwendet zu werden, etwa beim Neustart eines Nodes oder beim Übertragen eines Snapshots an einen anderen Node
    • Das heißt: Die Haupt-SQLite-Datei (bei Ignorieren der zugehörigen WAL-Datei) bleibt logisch identisch zu dem, was in den Raft-Snapshot-Store geschrieben worden wäre, wenn rqlite tatsächlich eine doppelte Kopie erstellt hätte
  • Dieses neue Design wird „Reference Snapshot“ genannt

Zusätzliche Verbesserungen

  • Reference Snapshots werden auch einige weitere wichtige Verbesserungen bringen
  • Schnellere Snapshot-Erstellung: Da nur minimale Daten in den Raft-Snapshot-Store geschrieben werden, wird der Snapshot-Prozess deutlich schneller sein
    • Er wird aus der SQLite-WAL-Checkpoint-Zeit (normalerweise sehr kurz) und der Zeit zur Berechnung der Prüfsumme bestehen
    • Es ist nicht mehr nötig, bei jeder Snapshot-Erstellung große Mengen an SQLite-Daten in den Snapshot-Store zu kopieren
    • Wenn man bedenkt, dass Schreibzugriffe auf rqlite während des Snapshot-Prozesses blockiert werden, liegt der Vorteil schnellerer Snapshots klar auf der Hand
  • Schnellere Neustarts: Selbst Nodes mit mehreren Gigabyte an SQLite-Daten werden deutlich schneller neu starten
    • Beim Neustart muss rqlite derzeit die Arbeits-SQLite-Datenbankdatei aus einer Kopie im Raft-Snapshot-Store wiederherstellen
    • Im neuen Design wird die Arbeits-SQLite-Datenbankdatei beim Start jedoch bereits am richtigen Ort vorhanden sein
    • Im besten Fall muss rqlite nur die Prüfsumme im Snapshot-Store mit der Prüfsumme der Arbeits-SQLite-Datenbank vergleichen
    • Systeme mit mehreren GB sollten innerhalb weniger Sekunden neu starten können

Nächste Schritte

  • Der Übergang zu rqlite 9.0 wird ein wichtiger Schritt bei der Optimierung der Effizienz von rqlite sein
  • Durch die Implementierung von Reference Snapshots wird erwartet, dass der Festplattenverbrauch deutlich sinkt, die Snapshot-Erstellung beschleunigt und die Neustartzeit von Nodes verbessert wird
  • Es gibt viele Details, die korrekt umgesetzt werden müssen, darunter die Verwaltung von SQLite WAL, reibungslose Upgrades von früheren Releases und die Auswahl der Prüfsumme
  • Daher sollte man die weiteren Updates auf dem Weg zu diesem Major Release im Blick behalten