Mobile-Menu

Speichertipp: Schnelle eingebettete Schlüssel-Werte-Datenbank mit ACID-Transaktionen und SSD-Optimierung BadgerDB in Go

Von Thomas Joos 4 min Lesedauer

Anbieter zum Thema

BadgerDB bringt Hochleistung in Go-Projekte. Die Datenbank arbeitet speicher- und transaktionssicher, nutzt moderne LSM-Architektur, trennt Schlüssel und Werte und läuft in Produktionsumgebungen mit mehreren Terabyte Daten.

Die Schlüssel-Werte-Datenbank BadgerDB ist auf Leistung und Persistenz ausgelegt.(Bild:  Midjourney / KI-generiert)
Die Schlüssel-Werte-Datenbank BadgerDB ist auf Leistung und Persistenz ausgelegt.
(Bild: Midjourney / KI-generiert)

BadgerDB als eingebettete Schlüssel-Werte-Datenbank (in Go geschrieben) bietet eine konsequent auf Leistung und Persistenz ausgelegte Architektur. Die Engine bildet das Speichersystem unterhalb von Dgraph und wird zunehmend in Projekten wie Jaeger Tracing oder UsenetExpress eingesetzt. Im Kern dient sie als Go-native Alternative zu RocksDB oder BoltDB, optimiert für SSDs und ausgelegt auf gleichzeitige ACID-Transaktionen mit serieller Snapshot-Isolation.

Aufbau und Installation

Badger erfordert Go ab Version 1.23. Die Bibliothek lässt sich mit dem Befehl

go get github.com/dgraph-io/badger/v4

in ein Go-Projekt einbinden. Das Kommandozeilenwerkzeug wird über

go install github.com/dgraph-io/badger/v4/badger@latest

installiert und steht anschließend im „$GOBIN“-Pfad zur Verfügung.

Die Datenbank wird über „badger.Open()“ geöffnet. Dabei sind die Parameter „Dir“ und „ValueDir“ zwingend erforderlich. Beide können auf denselben Pfad verweisen, da Badger auf dieser Ebene einen exklusiven Dateisystem-Lock setzt. Damit ist sichergestellt, dass kein zweiter Prozess gleichzeitig dieselbe Datenbank öffnet.

Badger kann alternativ vollständig im Speicher betrieben werden. Dafür genügt die Option „WithInMemory(true)“. Diese Variante verzichtet auf jede Persistenz, beschleunigt jedoch Lese- und Schreiboperationen erheblich. Wird Verschlüsselung aktiviert, muss zusätzlich der Index-Cache festgelegt werden, etwa mit „opts.IndexCache = 100 << 20“ für eine Zwischenspeicherung von 100 MB.

Transaktionen und Konfliktbehandlung

Transaktionen bilden das Herzstück von Badger. Eine lesende Transaktion wird mit „DB.View()“ gestartet, während „DB.Update()“ Schreibvorgänge ermöglicht. Beide Methoden kapseln automatisch das Anlegen, Committen und Aufräumen von Transaktionen.

Badger erkennt Konflikte über „ErrConflict „und signalisiert über „ErrTxnTooBig“, wenn eine Transaktion zu viele Operationen enthält. In diesem Fall sollte sie abgeschlossen und eine neue gestartet werden. Alternativ kann der Entwickler Transaktionen manuell verwalten. Über „DB.NewTransaction(true)“ wird eine schreibende Transaktion erzeugt, die explizit per „Txn.Commit()“ abgeschlossen werden muss. Ein optionaler Callback erlaubt asynchrones Committen, wodurch Schreibvorgänge parallelisiert werden können.

Arbeiten mit Schlüssel-Werte-Paaren

Neue Werte werden mit „Txn.Set()“ oder über ein Entry-Objekt geschrieben, das sich mit Metadaten und TTL erweitern lässt. Über „Entry.WithTTL(time.Hour)“ werden Einträge nach Ablauf der angegebenen Dauer gelöscht. Die Methode „Entry.WithMeta()“ erlaubt die Hinterlegung eines zusätzlichen Bytes zur Markierung von Datensätzen.

Werte lassen sich mit „Txn.Get()“ abrufen. Dabei bleiben Rückgabepuffer nur innerhalb der laufenden Transaktion gültig und müssen kopiert werden, falls sie außerhalb weiterverwendet werden sollen. Das Löschen erfolgt über „Txn.Delete()“.

Für sequentielle IDs stellt Badger mit „DB.GetSequence()“ eine Lösung bereit, die fortlaufende Integer-Werte über verschiedene Go-Routinen hinweg konsistent vergibt.

Merge-Operator und Zähler

Die API unterstützt Merge-Operationen über benutzerdefinierte Funktionen vom Typ MergeFunc. Damit lassen sich beispielsweise Bytefolgen zusammenführen oder Zähler inkrementieren. Der Merge-Operator wird über „DB.GetMergeOperator()“ aufgerufen, führt die Operationen periodisch aus und speichert das kumulierte Ergebnis im Hintergrund.

Iteration und Prefix-Scans

Zur Durchmusterung von Schlüsseln steht der Iterator „Txn.NewIterator()“ bereit. Er arbeitet lexikografisch sortiert und kann über Optionen wie „PrefetchSize“ oder „PrefetchValues“ konfiguriert werden. Für präfixbasierte Scans wird „Seek()“ mit „ValidForPrefix()“ kombiniert, um bestimmte Schlüsselbereiche effizient zu durchsuchen. Badger erlaubt zudem Key-only-Iterationen, bei denen ausschließlich die Schlüssel geladen werden. Diese Variante greift nur auf die LSM-Struktur zu, die meist vollständig im Arbeitsspeicher liegt, und ermöglicht sehr schnelle Scans.

Garbage Collection und Speicherverwaltung

Da Badger Werte getrennt von der LSM-Struktur ablegt, muss die Datenbereinigung separat erfolgen. Die Methode „DB.RunValueLogGC()“ prüft regelmäßig die Nutzungsstatistiken der Value-Logs und entfernt veraltete Segmente. Eine typische Routine ruft die Garbage Collection in festen Intervallen auf und wiederholt sie, solange sie erfolgreich Speicher freigibt.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Data-Storage und -Management

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung. Die Einwilligungserklärung bezieht sich u. a. auf die Zusendung von redaktionellen Newslettern per E-Mail und auf den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern (z. B. LinkedIn, Google, Meta).

Aufklappen für Details zu Ihrer Einwilligung

Die Speicherbelegung lässt sich über Parameter wie „NumMemtables“, „NumCompactors“, „BaseTableSize“ und „ValueLogFileSize“ anpassen. Reduzierte Werte senken den RAM-Bedarf, wirken sich jedoch auf die Schreibleistung aus.

Backups und Wiederherstellung

Für Sicherungen stellt Badger die APIs „DB.Backup()“ und „DB.Load()“ bereit. Zusätzlich existiert das CLI-Tool badger, das vollständige oder inkrementelle Backups offline erstellt. Die Dateien sind versionsunabhängig und lassen sich mit „badger restore“ in eine neue Datenbank zurückspielen.

Da alle SSTables unveränderlich sind und nur der aktuelle Value-Log fortlaufend beschrieben wird, ist Badger zudem mit Tools wie rsync kompatibel. Dadurch lassen sich Sicherungen während des Betriebs konsistent anfertigen.

Stabilität und Einsatzgebiete

Badger gilt als ausgereift und läuft in produktiven Systemen mit Datenmengen im dreistelligen Terabyte-Bereich. Nächtliche Banktests über acht Stunden sichern die Transaktionskonsistenz unter Wettlaufbedingungen. Das System bleibt auch bei Dateisystemfehlern konsistent und erfüllt vollständig die ACID-Anforderungen.

Die Architektur orientiert sich am WiscKey-Ansatz, der Schlüssel und Werte trennt und so die Schreiblatenz reduziert. Gegenüber RocksDB bietet Badger Vorteile bei SSD-Optimierung, Schreibdurchsatz und Go-Integration ohne Cgo-Abhängigkeiten.

Damit positioniert sich BadgerDB als performantes Fundament für datenintensive Go-Anwendungen, die auf eingebettete, transaktionssichere und speichereffiziente Schlüssel-Wert-Strukturen angewiesen sind.

Aktuelles eBook

Open-Source-Storage – Speicher-Software zum Nulltarif

eBook Open-Source-Storage
eBook „Open-Source-Storage“
(Bild: Storage-Insider)

Der Bedarf an Speicherkapazität steigt von Tag zu Tag – nicht nur, um die Daten von Produkten, Kunden und Transaktionen zu sichern, sondern auch, um Compliance-Anforderungen zu erfüllen und Auditierungen gut zu überstehen. Eine leistungsfähige Storage-Lösung ist also gefragt. Eine kostenlose Option bietet Open-Source-Software für Storage, insbesondere dann, wenn man sie selbst den eigenen Anforderungen anpassen darf.

Die Themen im Überblick:

  • Warum Storage als Open Source?
  • NAS & Objektspeicher
  • Backup & Disaster Recovery
  • Dateisysteme
  • Technologiestapel & Ökosysteme

(ID:50638740)