Zum Inhalt
wannacode

Wie du eine Datenbank wählst

Kurz gesagt: Wähle eine Datenbank nach deinen Daten und den Fragen, die du an sie stellst: Eine relationale Datenbank hält die Wahrheit, und eine andere Art kommt nur dort daneben, wo sie schwach ist.

Problem

Viele Arten von Datenbanken auf dem Tisch

Das Modul hat Key-Value, Dokumente, Ereignisströme, Graphen, Spalten und Zeitreihen, Textsuche, Vektoren und Cluster gezeigt. Jede dieser Datenbanken ist in etwas hervorragend. Das neue Projekt des Shops fragt: Welche wählen wir?

Der falsche Weg ist, bei der Datenbank anzufangen („wir nehmen MongoDB, weil es modern ist“). Der richtige Weg ist, bei den Daten und den Fragen anzufangen, die du an sie stellen wirst, und eine neue Datenbank erst dazuzunehmen, wenn es eine Frage gibt, die die Hauptdatenbank nicht gut beantwortet.

Die Idee

Fünf Fragen

  1. Welche Form haben die Daten? Zeilen mit denselben Spalten, ganze Dokumente mit verschachtelten Teilen, Verbindungen zwischen Dingen, Einträge über die Zeit, freier Text.
  2. Was fragst du? Eine Sache über einen Schlüssel, einen Bericht über alles, „wer ist mit wem verbunden“, „welche Wörter“, „was ist ähnlich“.
  3. Wie wichtig ist Konsistenz? Geld und Bestand brauchen Transaktionen und das Lesen des letzten Schreibvorgangs. Ein Like-Zähler darf eine Sekunde hinterherhinken.
  4. Wie groß sind die Daten und die Last? Tausende oder Milliarden Zeilen, zehn- oder hunderttausend Abfragen pro Sekunde. Die meisten Projekte sind viel kleiner, als sie denken.
  5. Wer kümmert sich darum? Jede Datenbank braucht Kopien, Monitoring, Updates und jemanden, der weiß, was zu tun ist, wenn sie ausfällt.
Die Frage Art der Datenbank
Geld, Bestellungen, Bestand, alles, was stimmen muss relational (PostgreSQL, MySQL)
Dasselbe tausendfach über einen Schlüssel, Sitzungen, Warenkörbe Key-Value (Redis)
Ganze Objekte mit verschiedenen Strukturen Dokumentendatenbank (MongoDB) oder JSONB
Viele Systeme erfahren vom selben Ereignis Ereignisstrom (Kafka)
Empfehlungen, Netzwerke, Betrug über mehrere Schritte Graph (Neo4j)
Berichte über Millionen Zeilen, Sensoren, Metriken spaltenorientiert, Zeitreihen (ClickHouse, TimescaleDB)
Ein Suchfeld, Wörter im Text Volltextsuche (Elasticsearch)
„Ähnlich in der Bedeutung“, ein Chatbot über Dokumente Vektor (pgvector, Qdrant)

Die Idee

Fang mit PostgreSQL an

Für die meisten neuen Projekte ist ein einziger relationaler Datenbankserver der vernünftige Start. PostgreSQL allein deckt einen großen Teil des Moduls ab: JSONB-Spalten für Dokumente, tsvector für die Textsuche, pgvector für Vektoren, TimescaleDB für Zeitreihen, Lese-Replikate und das Aufteilen von Tabellen nach Zeit. Es ist nicht in jedem davon das Beste, aber gut genug, und eine Datenbank ist viel einfacher zu betreuen als fünf.

Eine eigene Datenbank lohnt sich, wenn es eine konkrete Frage gibt, die die Hauptdatenbank langsam oder schwer beantwortet, und du das gemessen hast: der Cache, weil dieselbe Abfrage 2000-mal pro Minute läuft; die Suchmaschine, weil die Suche die Hauptaufgabe der Seite ist; das Data Warehouse, weil die Berichte die Kasse bremsen.

Genauer, für Neugierige

Das nennt man Polyglot Persistence: verschiedene Datenbanken für verschiedene Teile des Systems. Es funktioniert gut, wenn eine davon klar die Quelle der Wahrheit ist und die anderen Kopien sind, die sich neu aufbauen lassen. Es funktioniert schlecht, wenn zwei Datenbanken verschiedene Teile derselben Wahrheit halten und niemand weiß, welche stimmt.

Sieh es dir an

Der Shop, wenn er wächst

So könnte der Shop nach ein paar Jahren aussehen, jeder Teil dann dazugekommen, als er gebraucht wurde:

  • PostgreSQL hält die Kunden, die Produkte, die Bestellungen und die Zahlungen. Das ist die Wahrheit. Sie hat ein synchrones und ein asynchrones Replikat.
  • Redis hält den Cache des Katalogs, die Sitzungen und die Warenkörbe.
  • Kafka trägt die Ereignisse „Bestellung aufgegeben“, „bezahlt“, „versandt“ zum Lager, zu den Rechnungen und zur E-Mail.
  • Elasticsearch hält eine Kopie der Produkte und Bewertungen für das Suchfeld. Es wird aus den Ereignissen gefüllt.
  • ClickHouse ist das Data Warehouse für die Berichte. Es wird jede Nacht oder aus dem Strom gefüllt.
  • pgvector in derselben PostgreSQL liefert „ähnliche Produkte“.

Alle Kopien kommen aus PostgreSQL. Geht der Index in Elasticsearch kaputt, wird er aus der Datenbank neu aufgebaut. Umgekehrt geht das nicht.

Problem

Die zwei Schreibvorgänge

Die Bestellung wird nach PostgreSQL geschrieben, und dann sendet das Programm ein Ereignis an Kafka. Stürzt das Programm dazwischen ab, steht die Bestellung in der Datenbank, aber das Ereignis fehlt: Das Lager packt nie das Paket. Ist es umgekehrt (erst das Ereignis, dann die Datenbank), packt das Lager vielleicht ein Paket für eine Bestellung, die später scheitert.

Die zwei Systeme haben keine gemeinsame Transaktion. Die Lösung ist eine Outbox-Tabelle: Das Ereignis wird in eine Tabelle in derselben Datenbank geschrieben, in derselben Transaktion wie die Bestellung. Entweder werden beide geschrieben, oder keins.

SQLDatenbank: Shop

published_at ist NULL: Das Ereignis wurde noch nicht gesendet. Ein eigenes Programm (ein Relay) liest die ungesendeten der Reihe nach, sendet sie an den Strom und markiert sie erst dann:

SQLDatenbank: Shop

Und schlägt vor dem COMMIT etwas fehl, gibt es weder eine Änderung noch ein Ereignis:

SQLDatenbank: Shop
Genauer, für Neugierige

Das Relay kann abstürzen, nachdem es das Ereignis gesendet hat, aber bevor es es markiert. Dann sendet es beim Neustart erneut. Deshalb müssen die Empfänger des Ereignisses idempotent sein, wie die Rechnungen in der Lektion über Ströme. Statt eines Programms, das die Tabelle liest, nimmt man oft Debezium: Es liest das Änderungsprotokoll von PostgreSQL (das WAL) und sendet jede neue Zeile der Outbox an Kafka. Das heißt Change Data Capture (CDC).

Probier es aus

Eine Bestellung stornieren

Der Kunde storniert Bestellung 42. Ändere in einer Transaktion ihren Status auf cancelled und schreibe ein Ereignis in die Outbox für das Topic orders mit dem Schlüssel order-42 und dem Inhalt {"order":42,"event":"cancelled"}.

SQLDatenbank: Shop

Übung

Fünf Projekte

Für jedes Projekt: Welche Datenbank ist das Fundament, oder was fügst du daneben hinzu?

1. Eine Bank führt Konten und die Überweisungen zwischen ihnen. Die Summe aller Konten darf nie abweichen. Was ist das Fundament?
2. Eine Lieferapp zeigt, wo der Kurier ist. Jeder Kurier sendet alle 5 Sekunden seine Koordinaten, und das Diagramm zeigt die letzte Stunde. Was passt am besten zu diesen Daten?
3. Ein Kleinanzeigenportal will „ähnliche Anzeigen“ nach Text und Fotos, nicht nach gleichen Wörtern. Was fügst du neben der Hauptdatenbank hinzu?
4. Eine Lernplattform führt Kurse mit verschiedenen Strukturen: Kapitel, Lektionen, Videos, Tests, alles verschachtelt und bei jedem Kurs anders. Ein ganzer Kurs wird auf einmal gelesen und geschrieben. Was passt am natürlichsten?
5. Ein Shop mit 300 Bestellungen am Tag, einem Programmierer und PostgreSQL. Der Chef hat gelesen, dass die Großen Sharding nutzen. Was tust du?

Test

Teste dich

1. Das Programm schreibt die Bestellung nach PostgreSQL und sendet dann ein Ereignis an Kafka. Was passiert, wenn es dazwischen abstürzt?
2. Was stimmt für jede neue Datenbank in einem Projekt?
3. Der Cache in Redis, der Index in Elasticsearch und das Data Warehouse haben eine Kopie der Bestellungen. Wo ist die Wahrheit?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·