Direkt zum Hauptinhalt

Eintauchen in Delta Lake: Das Transaktionsprotokoll auspacken

Diving Into Delta Lake: Unpacking The Transaction Log

Veröffentlicht: 21. August 2019

Produkt10 min Lesezeit

Delta Lake logo.
Das Transaktionsprotokoll ist der Schlüssel zum Verständnis von Delta Lake, da es der rote Faden ist, der sich durch viele seiner wichtigsten Funktionen zieht, darunter ACID-Transaktionen, skalierbare Metadatenverarbeitung, Zeitreise und mehr. In diesem Artikel werden wir untersuchen, was das Delta Lake-Transaktionsprotokoll ist, wie es auf Dateiebene funktioniert und wie es eine elegante Lösung für das Problem mehrerer gleichzeitiger Lese- und Schreibvorgänge bietet.

Was ist das Delta Lake-Transaktionsprotokoll?

Das Delta Lake-Transaktionsprotokoll (auch bekannt als DeltaLog) ist eine geordnete Aufzeichnung jeder Transaktion, die jemals an einer Delta Lake-Tabelle seit ihrer Erstellung durchgeführt wurde.

Wofür wird das Transaktionsprotokoll verwendet?

Single Source of Truth

Delta Lake basiert auf Apache Spark™, um mehreren Lesern und Schreibern einer bestimmten Tabelle zu ermöglichen, gleichzeitig an der Tabelle zu arbeiten. Um den Benutzern jederzeit korrekte Ansichten der Daten anzuzeigen, dient das Delta Lake-Transaktionsprotokoll als Single Source of Truth – das zentrale Repository, das alle Änderungen verfolgt, die Benutzer an der Tabelle vornehmen.

Wenn ein Benutzer zum ersten Mal eine Delta Lake-Tabelle liest oder eine neue Abfrage auf einer geöffneten Tabelle ausführt, die seit dem letzten Lesen geändert wurde, überprüft Spark das Transaktionsprotokoll, um festzustellen, welche neuen Transaktionen in der Tabelle veröffentlicht wurden, und aktualisiert dann die Tabelle des Endbenutzers mit diesen neuen Änderungen. Dies stellt sicher, dass die Version einer Tabelle eines Benutzers immer mit dem Masterdatensatz ab dem Zeitpunkt der letzten Abfrage synchronisiert ist und dass Benutzer keine abweichenden, widersprüchlichen Änderungen an einer Tabelle vornehmen können.

Die Implementierung der Atomizität in Delta Lake

Eine der vier Eigenschaften von ACID-Transaktionen, die Atomizität, garantiert, dass Operationen (wie ein INSERT oder UPDATE), die auf Ihrem Data Lake ausgeführt werden, entweder vollständig abgeschlossen werden oder gar nicht. Ohne diese Eigenschaft kann ein Hardwarefehler oder ein Softwarefehler allzu leicht dazu führen, dass Daten nur teilweise in eine Tabelle geschrieben werden, was zu unordentlichen oder beschädigten Daten führt.

Das Transaktionsprotokoll ist der Mechanismus, durch den Delta Lake die Garantie der Atomizität bieten kann. Für alle praktischen Zwecke gilt: Wenn es nicht im Transaktionsprotokoll aufgezeichnet ist, ist es nie geschehen. Indem nur Transaktionen aufgezeichnet werden, die vollständig und vollständig ausgeführt werden, und diese Aufzeichnung als Single Source of Truth verwendet wird, ermöglicht das Delta Lake-Transaktionsprotokoll den Benutzern, über ihre Daten nachzudenken und sich auf Petabyte-Ebene auf deren grundlegende Vertrauenswürdigkeit zu verlassen.

Wie funktioniert das Transaktionsprotokoll?

Aufteilen von Transaktionen in atomare Commits

Immer wenn ein Benutzer eine Operation zur Änderung einer Tabelle durchführt (z. B. ein INSERT, UPDATE oder DELETE), unterteilt Delta Lake diese Operation in eine Reihe diskreter Schritte, die aus einer oder mehreren der folgenden Aktionen bestehen.

  • Datei hinzufügen – fügt eine Datendatei hinzu.
  • Datei entfernen – entfernt eine Datendatei.
  • Metadaten aktualisieren – Aktualisiert die Metadaten der Tabelle (z. B. Ändern des Namens, des Schemas oder der Partitionierung der Tabelle).
  • Transaktion festlegen – Zeichnet auf, dass ein Structured Streaming-Job einen Micro-Batch mit der angegebenen ID committet hat.
  • Protokoll ändern – aktiviert neue Funktionen, indem das Delta Lake-Transaktionsprotokoll auf das neueste Softwareprotokoll umgestellt wird.
  • Commit-Info – Enthält Informationen zum Commit, welche Operation durchgeführt wurde, von wo und zu welcher Zeit.

Diese Aktionen werden dann im Transaktionsprotokoll als geordnete, atomare Einheiten aufgezeichnet, die als Commits bezeichnet werden.

Nehmen wir beispielsweise an, ein Benutzer erstellt eine Transaktion, um einer Tabelle eine neue Spalte hinzuzufügen und weitere Daten hinzuzufügen. Delta Lake würde diese Transaktion in ihre Bestandteile zerlegen und sie nach Abschluss der Transaktion als die folgenden Commits zum Transaktionsprotokoll hinzufügen:

  1. Metadaten aktualisieren – Ändern Sie das Schema, um die neue Spalte einzuschließen
  2. Datei hinzufügen – für jede neue hinzugefügte Datei

Das Delta Lake-Transaktionsprotokoll auf Dateiebene

Wenn ein Benutzer eine Delta Lake-Tabelle erstellt, wird das Transaktionsprotokoll dieser Tabelle automatisch im Unterverzeichnis _delta_log erstellt. Wenn er Änderungen an dieser Tabelle vornimmt, werden diese Änderungen als geordnete, atomare Commits im Transaktionsprotokoll aufgezeichnet. Jeder Commit wird als JSON-Datei ausgegeben, beginnend mit 000000.json. Zusätzliche Änderungen an der Tabelle generieren nachfolgende JSON-Dateien in aufsteigender numerischer Reihenfolge, sodass der nächste Commit als 000001.json, der folgende als 000002.json usw. ausgegeben wird.

Diagramm der Dateistruktur des Delta Lake-Transaktionsprotokolls.

Nehmen wir also beispielsweise an, wir fügen unserer Tabelle zusätzliche Datensätze aus den Datendateien 1.parquet und 2.parquet hinzu. Diese Transaktion würde automatisch dem Transaktionsprotokoll hinzugefügt und als Commit 000000.json auf der Festplatte gespeichert. Dann ändern wir vielleicht unsere Meinung und beschließen, diese Dateien zu entfernen und stattdessen eine neue Datei (3.parquet) hinzuzufügen. Diese Aktionen würden als nächster Commit im Transaktionsprotokoll als 000001.json aufgezeichnet, wie unten gezeigt.

Diagramm zur Veranschaulichung von zwei Commits, die Operationen an derselben Datei ausführen.

Auch wenn 1.parquet und 2.parquet nicht mehr Teil unserer Delta Lake-Tabelle sind, werden ihre Hinzufügung und Entfernung dennoch im Transaktionsprotokoll aufgezeichnet, da diese Operationen an unserer Tabelle durchgeführt wurden – trotz der Tatsache, dass sie sich letztendlich gegenseitig aufgehoben haben. Delta Lake behält dennoch atomare Commits wie diese bei, um sicherzustellen, dass wir im Falle einer Überprüfung unserer Tabelle oder der Verwendung von „Zeitreisen“ sehen können, wie unsere Tabelle zu einem bestimmten Zeitpunkt aussah.

Außerdem entfernt Spark die Dateien nicht sofort von der Festplatte, auch wenn wir die zugrunde liegenden Datendateien aus unserer Tabelle entfernt haben. Benutzer können die nicht mehr benötigten Dateien mit VACUUM löschen.

Schnelles Neuberechnen des Status mit Checkpoint-Dateien

Sobald wir mehrere Commits am Transaktionsprotokoll vorgenommen haben, speichert Delta Lake eine Checkpoint-Datei im Parquet-Format im selben Unterverzeichnis _delta_log. Delta Lake generiert automatisch Checkpoints nach Bedarf, um eine gute Leseleistung aufrechtzuerhalten.

Diagramm zur Veranschaulichung der Dateistruktur des Delta Lake-Transaktionsprotokolls, einschließlich Partitionsverzeichnissen.

Diese Checkpoint-Dateien speichern den gesamten Status der Tabelle zu einem bestimmten Zeitpunkt – im nativen Parquet-Format, das Spark schnell und einfach lesen kann. Mit anderen Worten, sie bieten dem Spark-Reader eine Art „Abkürzung“ zur vollständigen Reproduktion des Status einer Tabelle, die es Spark ermöglicht, die Neuverarbeitung von möglicherweise Tausenden von kleinen, ineffizienten JSON-Dateien zu vermeiden.

Um auf dem neuesten Stand zu sein, kann Spark eine listFrom-Operation ausführen, um alle Dateien im Transaktionsprotokoll anzuzeigen, schnell zur neuesten Checkpoint-Datei zu springen und nur die JSON-Commits zu verarbeiten, die seit dem Speichern der letzten Checkpoint-Datei vorgenommen wurden.

Um zu demonstrieren, wie dies funktioniert, stellen Sie sich vor, wir haben Commits bis einschließlich 000007.json erstellt, wie im Diagramm unten dargestellt. Spark ist durch diesen Commit auf dem neuesten Stand und hat automatisch die neueste Version der Tabelle im Speicher zwischengespeichert. In der Zwischenzeit haben jedoch mehrere andere Schreiber (vielleicht Ihre übereifrigen Teamkollegen) neue Daten in die Tabelle geschrieben und Commits bis einschließlich 0000012.json hinzugefügt.

Um diese neuen Transaktionen zu integrieren und den Status unserer Tabelle zu aktualisieren, führt Spark dann eine listFrom version 7-Operation aus, um die neuen Änderungen an der Tabelle anzuzeigen.

Diagramm zur Veranschaulichung, wie Spark aktuelle Checkpoint-Dateien liest, um den Tabellenstatus schnell zu berechnen.

Anstatt alle zwischengeschalteten JSON-Dateien zu verarbeiten, kann Spark zur neuesten Checkpoint-Datei springen, da sie den gesamten Status der Tabelle bei Commit Nr. 10 enthält. Jetzt muss Spark nur noch die inkrementelle Verarbeitung von 0000011.json und 0000012.json durchführen, um den aktuellen Status der Tabelle zu erhalten. Spark speichert dann Version 12 der Tabelle im Speicher zwischen. Durch Befolgen dieses Workflows kann Delta Lake Spark verwenden, um den Status einer Tabelle jederzeit effizient zu aktualisieren.

Umgang mit mehreren gleichzeitigen Lese- und Schreibvorgängen

Nachdem wir nun verstanden haben, wie das Delta Lake-Transaktionsprotokoll auf hoher Ebene funktioniert, wollen wir über Parallelität sprechen. Bisher haben unsere Beispiele hauptsächlich Szenarien behandelt, in denen Benutzer Transaktionen linear oder zumindest ohne Konflikte committen. Was passiert aber, wenn Delta Lake mit mehreren gleichzeitigen Lese- und Schreibvorgängen zu tun hat?

Die Antwort ist einfach. Da Delta Lake von Apache Spark unterstützt wird, ist es nicht nur möglich, dass mehrere Benutzer eine Tabelle gleichzeitig ändern – es wird auch erwartet. Um diese Situationen zu bewältigen, verwendet Delta Lake die optimistische Parallelitätskontrolle.

Was ist optimistische Parallelitätskontrolle?

Die optimistische Parallelitätskontrolle ist eine Methode zum Umgang mit gleichzeitigen Transaktionen, die davon ausgeht, dass Transaktionen (Änderungen), die von verschiedenen Benutzern an einer Tabelle vorgenommen werden, abgeschlossen werden können, ohne miteinander in Konflikt zu geraten. Sie ist unglaublich schnell, da bei der Verarbeitung von Petabyte an Daten eine hohe Wahrscheinlichkeit besteht, dass Benutzer an völlig unterschiedlichen Teilen der Daten arbeiten, sodass sie nicht in Konflikt stehende Transaktionen gleichzeitig abschließen können.

Stellen Sie sich beispielsweise vor, Sie und ich arbeiten zusammen an einem Puzzlespiel. Solange wir beide an verschiedenen Teilen davon arbeiten – Sie beispielsweise an den Ecken und ich an den Kanten –, gibt es keinen Grund, warum wir nicht gleichzeitig an unserem Teil des größeren Puzzles arbeiten und das Puzzle doppelt so schnell fertigstellen können. Nur wenn wir die gleichen Teile zur gleichen Zeit benötigen, kommt es zu einem Konflikt. Das ist optimistische Parallelitätskontrolle.

Selbst bei optimistischer Parallelitätskontrolle versuchen Benutzer manchmal, dieselben Teile der Daten gleichzeitig zu ändern. Glücklicherweise verfügt Delta Lake über ein Protokoll dafür.

Konflikte optimistisch lösen

Um ACID-Transaktionen anzubieten, verfügt Delta Lake über ein Protokoll, um herauszufinden, wie Commits geordnet werden sollen (bekannt als das Konzept der Serialisierbarkeit in Datenbanken), und um zu bestimmen, was im Falle von zwei oder mehr gleichzeitig vorgenommenen Commits zu tun ist. Delta Lake behandelt diese Fälle durch die Implementierung einer Regel der gegenseitigen Ausschließung, und versucht dann, jeden Konflikt optimistisch zu lösen. Dieses Protokoll ermöglicht es Delta Lake, das ACID-Prinzip der Isolation zu erfüllen, das sicherstellt, dass der resultierende Zustand der Tabelle nach mehreren gleichzeitigen Schreibvorgängen derselbe ist, als ob diese Schreibvorgänge seriell, isoliert voneinander erfolgt wären.

Im Allgemeinen läuft der Prozess wie folgt ab:

  1. Zeichnen Sie die Starttabellenversion auf.
  2. Zeichnen Sie Lese-/Schreibvorgänge auf.
  3. Versuchen Sie einen Commit.
  4. Wenn jemand anderes gewinnt, überprüfen Sie, ob sich etwas, das Sie gelesen haben, geändert hat.
  5. Wiederholen.

Um zu sehen, wie sich das alles in Echtzeit abspielt, werfen wir einen Blick auf das Diagramm unten, um zu sehen, wie Delta Lake Konflikte verwaltet, wenn sie auftreten. Stellen Sie sich vor, zwei Benutzer lesen aus derselben Tabelle und versuchen dann jeweils, einige Daten hinzuzufügen.

Veranschaulichung der optimistischen Parallelitätskontrolle durch die Anzeige von zwei Benutzern mit in Konflikt stehenden Commits.

  • Delta Lake zeichnet die Starttabellenversion der Tabelle (Version 0) auf, die vor dem Vornehmen von Änderungen gelesen wird.
  • Benutzer 1 und 2 versuchen beide gleichzeitig, einige Daten an die Tabelle anzuhängen. Hier sind wir auf einen Konflikt gestoßen, da nur ein Commit als Nächstes erfolgen und als 000001.json aufgezeichnet werden kann.
  • Delta Lake behandelt diesen Konflikt mit dem Konzept der „gegenseitigen Ausschließung“, was bedeutet, dass nur ein Benutzer erfolgreich Commit 000001.json ausführen kann. Der Commit von Benutzer 1 wird akzeptiert, während der von Benutzer 2 abgelehnt wird.
  • Anstatt einen Fehler für Benutzer 2 auszugeben, zieht es Delta Lake vor, diesen Konflikt optimistisch zu behandeln. Es wird überprüft, ob neue Commits an der Tabelle vorgenommen wurden, und die Tabelle im Hintergrund aktualisiert, um diese Änderungen widerzuspiegeln, und dann der Commit von Benutzer 2 in der neu aktualisierten Tabelle (ohne Datenverarbeitung) einfach wiederholt, wodurch 000002.json erfolgreich committet wird.

In den allermeisten Fällen erfolgt diese Abstimmung im Hintergrund, nahtlos und erfolgreich. Sollte es jedoch ein unlösbares Problem geben, das Delta Lake nicht optimistisch lösen kann (z. B. wenn Benutzer 1 eine Datei gelöscht hat, die Benutzer 2 ebenfalls gelöscht hat), besteht die einzige Möglichkeit darin, einen Fehler auszugeben.

Abschließend sei gesagt, dass dieser Prozess die ACID-Eigenschaft der Dauerhaftigkeit erfüllt, da alle an Delta Lake-Tabellen vorgenommenen Transaktionen direkt auf der Festplatte gespeichert werden, was bedeutet, dass sie auch im Falle eines Systemausfalls bestehen bleiben.

5-FACHER LEADER

Gartner®: Databricks als Leader für Cloud-Datenbanken

Andere Anwendungsfälle

Zeitreisen

Jede Tabelle ist das Ergebnis der Summe aller im Delta Lake-Transaktionsprotokoll aufgezeichneten Commits – nicht mehr und nicht weniger. Das Transaktionsprotokoll bietet eine Schritt-für-Schritt-Anleitung, die genau beschreibt, wie man vom ursprünglichen Zustand der Tabelle in ihren aktuellen Zustand gelangt.

Daher können wir den Zustand einer Tabelle zu jedem beliebigen Zeitpunkt wiederherstellen, indem wir mit einer Originaltabelle beginnen und nur Commits verarbeiten, die vor diesem Zeitpunkt vorgenommen wurden. Diese leistungsstarke Fähigkeit wird als „Zeitreisen“ oder Datenversionierung bezeichnet und kann in einer Reihe von Situationen lebensrettend sein. Weitere Informationen finden Sie im Blogbeitrag Einführung von Delta Time Travel für Data Lakes im großen Maßstab oder in der Delta Lake-Zeitreisedokumentation.

Data Lineage und Debugging

Als definitive Aufzeichnung jeder jemals an einer Tabelle vorgenommenen Änderung bietet das Delta Lake-Transaktionsprotokoll Benutzern eine überprüfbare Data Lineage, die für Governance-, Audit- und Compliance-Zwecke nützlich ist. Es kann auch verwendet werden, um den Ursprung einer unbeabsichtigten Änderung oder eines Fehlers in einer Pipeline bis zu der genauen Aktion zurückzuverfolgen, die ihn verursacht hat. Benutzer können DESCRIBE HISTORY ausführen, um Metadaten zu den vorgenommenen Änderungen anzuzeigen.

Zusammenfassung des Delta Lake-Transaktionsprotokolls

In diesem Blog sind wir auf die Details der Funktionsweise des Delta Lake-Transaktionsprotokolls eingegangen, einschließlich:

  • Was das Transaktionsprotokoll ist, wie es strukturiert ist und wie Commits als Dateien auf der Festplatte gespeichert werden.
  • Wie das Transaktionsprotokoll als Single Source of Truth dient, die es Delta Lake ermöglicht, das Prinzip der Atomizität zu implementieren.
  • Wie Delta Lake den Status jeder Tabelle berechnet – einschließlich der Verwendung des Transaktionsprotokolls, um den Rückstand vom letzten Checkpoint aufzuholen.
  • Verwenden der optimistischen Parallelitätskontrolle, um mehrere gleichzeitige Lese- und Schreibvorgänge auch bei Änderungen an Tabellen zu ermöglichen.
  • Wie Delta Lake die gegenseitige Ausschließung verwendet, um sicherzustellen, dass Commits ordnungsgemäß serialisiert werden, und wie sie im Falle eines Konflikts im Hintergrund wiederholt werden.
Interessieren Sie sich für das Open-Source-Delta Lake?
Besuchen Sie den Delta Lake-Online-Hub, um mehr zu erfahren, den neuesten Code herunterzuladen und der Delta Lake-Community beizutreten.

Verwandte Themen

Artikel in dieser Serie:
Eintauchen in Delta Lake #1: Auspacken des Transaktionsprotokolls
Eintauchen in Delta Lake #2: Schema Enforcement & Evolution
Eintauchen in Delta Lake #3: DML-Interna (Aktualisieren, Löschen, Zusammenführen)

Verwandte Artikel:
Was ist ein Data Lake?
Produktionsreifes Machine Learning mit Delta Lake

(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag

Verpassen Sie keinen Beitrag von Databricks

Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.