Übersicht über das Datenspeichersystem

Zuverlässig, skalierbar und wartbar

Viele davon sind mittlerweile eher datenintensiv als rechenintensiv. Für diese Art von Anwendungen ist die Rechenleistung der CPU oft nicht der erste limitierende Faktor, der Schlüssel liegt in der Datenmenge, der Komplexität der Daten und der schnellen Polygonalität der Daten.
Datenintensive Anwendungsmodule:

  • Datenbank: Daten speichern und sekundären Zugriff unterstützen.
  • Cache: Zwischenspeichern Sie die Ergebnisse komplexer oder teurer Vorgänge, um den nächsten Zugriff zu beschleunigen.
  • Indizierung: Durchsuchen Sie Daten nach Schlüsselwörtern und unterstützen Sie verschiedene Filter.
  • Stream-Verarbeitung: Nachrichten kontinuierlich an einen anderen Prozess senden und asynchron verarbeiten.
  • Stapelverarbeitung: Verarbeiten Sie regelmäßig große Mengen an gesammelten Daten. Unsere gemeinsamen Datenbanken, Warteschlangen und Caches werden gemeinsam als „ Datensysteme
    bezeichnet . Das Folgende ist eine gemeinsame Systemarchitektur:

Fügen Sie hier eine Bildbeschreibung ein
In Wirklichkeit ist das Programm jedoch nicht ideal, wenn es ausgeführt wird, und es treten verschiedene Probleme auf. Beispiel: Wie kann die Richtigkeit und Integrität der Daten sichergestellt werden, wenn im System ein Teilfehler auftritt? Wie können Sie Ihren Kunden bei Downgrades einen konsistenten Service bieten? Wie skaliert das System bei steigender Last? Darauf aufbauend stellen wir die folgenden drei Systemfunktionen vor:

  • Zuverlässigkeit (Zuverlässigkeit)
    Bei Unfällen (Hardware-, Softwarefehler, menschliches Versagen usw.) sollte das System normal funktionieren; die Leistung kann reduziert sein, aber die normale Funktion ist gewährleistet.
  • Skalierbarkeit (Skalierbarkeit)
    Mit dem Wachstum des Datenumfangs, wie z. B. Datenvolumen, Datenverkehr oder Komplexität, sollte das System diesem Wachstum in angemessener Weise gerecht werden
  • Wartbarkeit (Maintainability)
    Wenn im Laufe der Zeit Neulinge in die Systementwicklung sowie den Betrieb und die Wartung einsteigen, sollte das System reibungslos laufen.

Zuverlässigkeit

Zu den typischen Erwartungen an Software gehören:

  • Die Anwendung führt die vom Benutzer erwarteten Funktionen aus.
  • Benutzerfehler oder falsche Verwendung können toleriert werden.
  • Die Leistung kann typische Szenarien, angemessenen Lastdruck und Datenvolumen bewältigen.
  • Das System ist vor unbefugtem Zugriff und Missbrauch geschützt.

Skalierbarkeit

Beschreibung Nutzlast

Schauen Sie sich zunächst die typischen Geschäftsabläufe von Twitter an:

  • Tweets veröffentlichen: Benutzer können Nachrichten an alle Follower senden, mit einem Durchschnitt von etwa 4,6.000 Anfragen/Sekunde und einem Spitzenwert von etwa 12.000 Anfragen/Sekunde.
  • Durchsuchen der Homepage-Timeline: Durchschnittlich 300.000 Anfragen/Sek. Sehen Sie sich die neuesten Nachrichten des betreffenden Objekts an.
    Aufmerksame Leute werden feststellen, dass es nicht darum geht, zu viele Nachrichten zu verbreiten, sondern um eine riesige Fan-out-Struktur: Jeder Benutzer wird vielen Leuten folgen und von vielen Leuten verfolgt werden. Die folgende Verarbeitung kann durchgeführt werden:
    (1) Einfügen der neu gesendeten Nachricht in die globale Tweet-Sammlung. Wenn der Benutzer die Zeitleiste anzeigt, sucht er zunächst alle Follower, listet alle Tweets dieser Personen auf und sortiert schließlich nach Zeit. Ähnliche SQL-Anweisungen:
SELECT tweets.*, users.* FROM tweets JOIN users ON tweets.sender_id = user.id JOIN follows ON follows.followee_id = users.id WHERE follows.follwer_id = current_user

Das relationale Modell unterstützt die Zeitleiste:
Fügen Sie hier eine Bildbeschreibung ein(2) Pflegen Sie einen Cache für die Zeitleiste jedes Benutzers, ähnlich einem Tweet-Postfach für jeden Benutzer. Wenn ein Benutzer einen neuen Tweet twittert, werden seine Follower abgefragt und der Tweet wird in den Timeline-Cache jedes Followers eingefügt. (Fügen Sie eine Ebene des Caching-Mechanismus hinzu)

Wie im Bild gezeigt: Fügen Sie hier eine Bildbeschreibung ein
Der offensichtliche Nachteil dieser Methode besteht darin, dass sie den Arbeitsaufwand erhöht. Bei 75 Followern und 4,6.000 Tweets pro Sekunde müssen 4,6 x 75 = 354.000 pro Sekunde in den Cache geschrieben werden. Wenn ein Benutzer eine große Fangemeinde hat, ist dies schwierig zu erreichen.
Wir können entsprechend der Häufigkeit des Twitterns durch den Benutzer gewichten. Derzeit wird Tweeten auf der Grundlage von Methode 2 implementiert, wir wechseln jedoch zu einer Methode, die die beiden Methoden kombiniert.

Wartbarkeit

Ein gutes Softwaresystem kann nicht einfach im ersten Moment stehen bleiben. Es müssen auch die späteren Wartungskosten und die Anpassungskosten von Neulingen berücksichtigt werden, die sich in drei Prinzipien zusammenfassen lassen:

  • Bedienbarkeit: Für das Betriebsteam ist es praktisch, dafür zu sorgen, dass das System reibungslos läuft. (Beobachtung, Überwachung, Automatisierung, Vorhersagbarkeit)
  • Einfachheit: Vereinfacht die Systemkomplexität, um neuen Ingenieuren das Verständnis des Systems zu erleichtern. (abstrakt, verständlich, klar, prägnant, elegant)
  • Evolvierbarkeit: Ingenieure können das System problemlos verbessern und an atypische Szenarien anpassen, wenn sich die Anforderungen ändern. Dies wird auch als Erweiterbarkeit, Modifizierbarkeit oder Plastizität bezeichnet.

Datenmodell und Abfragesprache

Die Entwicklung jeder Software ist untrennbar mit dem Datenmodell, also der Infrastruktur, verbunden. Komplexe Programme können viele Zwischenschichten haben, aber die Grundidee ist dieselbe: Jede Schicht verbirgt die Komplexität der darunter liegenden Schicht, indem sie ein prägnantes Datenmodell bereitstellt.

Datenmodell

hierarchisches Modell

Es stellt Daten verschachtelt in Datensätzen (Bäumen) dar, die Eins-zu-viele-Beziehungen unterstützen können, aber es ist schwieriger, viele-zu-viele-Beziehungen zu unterstützen. Um dieses Problem zu lösen, entstanden später ein relationales Modell und ein Netzwerkmodell.

relationales Modell

Das heute beliebteste Datenmodell ist SQL, dessen Ziel es ist, Implementierungsdetails hinter einer prägnanteren Schnittstelle zu verbergen. An zweiter Stelle steht NOSQL. Es kann einen extrem schnellen Schreibdurchsatz bieten und einige spezifische Abfragevorgänge unterstützen. Gegenwärtig werden viele Anwendungssysteme durch die Kombination beider implementiert.

Netzwerkmodell

Der Unterschied zum hierarchischen Modell besteht darin, dass ein Datensatz mehrere Eltern haben kann, die Verknüpfungen zwischen Datensätzen keine Fremdschlüssel sind, sondern eher wie Zeiger in der Sprache, und die einzige Möglichkeit, auf Daten zuzugreifen, darin besteht, einen Datensatz ausgehend von der Wurzel auszuwählen. (ähnlich wie Diagramm, verknüpfte Liste)

Dokumentmodell

Es löst hauptsächlich die Aggregation lokaler Informationen, die leicht gleichzeitig erkannt oder angezeigt werden können. Der offensichtlichere Nachteil besteht jedoch darin, dass keine gemeinsamen Operationsabfragen für mehrere Tabellen durchgeführt werden können.

Diagrammdatenmodell

Ein Diagramm besteht aus zwei Arten von Objekten: Scheitelpunkten (auch als Knoten/Entitäten bezeichnet) und Kanten (auch als Beziehungen/Bögen bezeichnet). Da die Beziehungen zwischen Daten immer komplexer werden, wird es natürlicher, Daten in einem Diagramm zu modellieren Modell.

Wie wählen wir bei so vielen Modellen eines aus? Durch die Beschreibung kann jeder auch die Eigenschaften jedes Modells kennen.

  • Die Anwendungsdaten ähneln Dokumenten (Eins-zu-Viele-Beziehungsbaum, indem der gesamte Baum auf einmal geladen wird), und es ist angemessener, das Dokumentmodell auszuwählen.
  • Das relationale Modell neigt eher zur Datenzerlegung und zerlegt das Dokumentmodell in mehrere Tabellen.
  • Diagramme eignen sich eher für soziale Netzwerke, Webdiagramme und Straßennetze
  • Die meisten Datenbanken unterstützen heutzutage Dokument- und relationale Tabellen.

Datenabfragesprache

Es gibt deklarative Abfragesprachen (SQL) und imperative Abfragesprachen (IMS, CODASYL).
Imperativ:

function getSharks() {
    
    
	var sharks = [];
	for (var i = 0; i < animals.length; i++) {
    
    
		if (annimals[i].family === "Sharks") {
    
    
			sharks.push(animals[i]);
		}
	}
}

SQL:

SELECT * FROM animals WHERE family = 'Sharks';

Ob die deklarative Sprache parallel ausgeführt wird, während die imperative Sprache auf Multi-Core- und mehreren Maschinen schwer zu parallelisieren ist, da sie eine bestimmte Ausführungsreihenfolge angibt.

MapReduce-Abfrage

Es handelt sich um ein Programmiermodell für die Stapelverarbeitung großer Datenmengen auf vielen Maschinen. Es ist weder deklarativ noch imperativ, sondern irgendwo dazwischen: Die Logik der Abfrage wird in Codefragmenten ausgedrückt, die von der Maschine wiederholt aufgerufen werden können. Es basiert auf den Funktionen Map (auch Collect genannt) und Reduce (auch Fold oder Inject genannt) in funktionalen Programmiersprachen.

Diagrammabfrage

Cypher (benannt nach einem Zeichen in „The Matrix“ ) ist eine deklarative Abfragesprache für Eigenschaftsdiagramme.

Ternärer Speicher und SPARQL

Bei der ternären Speicherung werden alle Informationen in einer sehr einfachen dreiteiligen Form (Subjekt, Prädikat, Objekt) gespeichert, wie zum Beispiel: (böser Junge, mögen, spielen), böser Junge ist das Subjekt, ebenso wie das Prädikat (Verb), Spielen ist das Ziel. Die Körper der Tripel entsprechen den Eckpunkten des Diagramms. Das Objekt ist einer der beiden folgenden Typen:

  1. Werte in primitiven Datentypen wie Zeichenfolgen oder Zahlen. Das Prädikat und das Objekt des Tripletts entsprechen dann dem Schlüssel bzw. dem Wert der Subjekteigenschaften (Scheitelpunkt). Zum Beispiel: (hxg, Alter, 26) ist wie der Scheitelpunkt hxg, Attribut {"Alter": 26}.
  2. Ein weiterer Scheitelpunkt im Diagramm. Zu diesem Zeitpunkt ist das Prädikat die Kante im Diagramm, das Subjekt ist der Schwanzscheitelpunkt und das Objekt ist der Kopfscheitelpunkt. Beispiel: (hxg, love, hxm), die Subjekte hxg und hxm sind beide Eckpunkte, und das Prädikat love ist die Bezeichnung der Kante, die sie verbindet.
    SPARQL (ausgesprochen: sparkle) ist eine ternäre gespeicherte Abfragesprache, die das RDF-Datenmodell verwendet.

Datenspeicherung und -abruf

Alle Systeme sind untrennbar mit der Dateninteraktion, der Datenspeicherung und dem Abruf/Erfassung verbunden. Eine einfachste Datenbank, die durch zwei Bash-Funktionen implementiert wird:

#!/bin/bash
db_set () {
    
    
	echo "$1,$2" >> database
}

db_get () {
    
    
	grep "^$1," database | sed -e "s/^$1,//" | tail -n 1
}

Diese beiden Funktionen implementieren einen Schlüsselwertspeicher. Rufen Sie den Schlüsselwert db_set auf und speichern Sie ihn direkt in der Datenbank (Datei). Diese Methode übernimmt die Methode des Anhängens. Wenn ein bestimmter Schlüssel mehrmals aktualisiert wird, wird die alte Version nicht überschrieben. Stattdessen wird direkt das letzte Vorkommen des Schlüssels überprüft, um den neuesten Wert zu finden (tail -n 1). Es ist jedoch offensichtlich, dass die Leistung der Funktion db_get sehr schlecht ist, wenn die Datei zu groß ist. Jedes Mal, wenn Sie einen Schlüssel erhalten, müssen Sie ihn von Anfang an durchlaufen, und die zeitliche Komplexität beträgt O (n). Daher gibt es das Konzept des Index, aber unabhängig vom Index erhöht es den Aufwand für die Aktualisierung der Daten.

Hash-Index

Der Index wird durch die Hash-Map (Hash-Tabelle) realisiert, wenn diese aus den oben genannten zusätzlichen Dateien besteht. Die Hash-Zuordnung im Speicher kann gespeichert werden, und jeder Schlüssel wird nacheinander einem bestimmten Byte-Offset in der Datendatei zugeordnet, sodass die Position jedes Werts ermittelt werden kann.
Fügen Sie hier eine Bildbeschreibung ein
Der Kernansatz von Bitcask (der Standardspeicher-Engine in Riak) ist das obige Beispiel. Es bietet leistungsstarkes Lesen und Schreiben. Solange alle Schlüssel im Speicher abgelegt werden können, ist nur eine Festplattenadressierung erforderlich, um den Wert in den Speicher zu laden. Natürlich reicht es nicht aus, nur eine Datei anzuhängen, es ist ein Protokollschneiden erforderlich. Eine Komprimierungsverarbeitung kann auch durchgeführt werden, um doppelte Schlüssel zu entfernen. Wenn sie komprimiert sind, können sie auch in eine neue Segmentdatei geschrieben werden und mehrere Segmente können gleichzeitig zusammengeführt werden. Bei einer realen Umsetzung stellen sich folgende wichtige Fragen:

  • Dateiformat: Das Anhängen des Protokolls sollte ein Binärformat verwenden, zuerst die Länge der Zeichenfolge in Bytes aufzeichnen und dann die ursprüngliche Länge der Zeichenfolge beibehalten
  • Datensatz löschen: Um einen Schlüssel zu löschen, muss eine spezielle Löschkennung (auch Tombstone genannt) an die Datendatei angehängt werden. Beim Zusammenführen von Dateien wird der Schlüssel verworfen, sobald ein Tombstone gefunden wird.
  • Absturzwiederherstellung: Wenn die Datenbank neu gestartet wird, geht die Speicher-Hash-Map verloren und wenn alle Scandateien geladen sind, dauert es lange. Bitcask speichert jeden Hash-Map-Snapshot auf der Festplatte, die schneller in den Speicher geladen werden kann.
  • Teilweise geschriebene Datensätze: Die Datenbank stürzt jederzeit ab, auch während des Anhängens von Datensätzen an das Protokoll. Bitcask-Dateien enthalten Prüfsummen, die teilweise beschädigt sind und verworfen werden können.
  • Parallelitätskontrolle: Da Datendateien angehängt, unveränderlich und nicht sequentiell geschrieben werden, können sie von mehreren Threads gleichzeitig gelesen werden.
  • Einschränkungen: Muss im Speicher gespeichert werden. Wenn das Datenvolumen des Schlüssels zu groß ist, sind die Kosten sehr hoch. Die Abfrage des Intervallbereichs ist äußerst ineffizient.
    Jemand fragte: Warum nicht die Datei an Ort und Stelle aktualisieren, sondern anhängen?
  • Erstens handelt es sich beim Anhängen und Zusammenführen von Segmenten hauptsächlich um sequentielle Schreibvorgänge, die viel schneller sind als zufällige Schreibvorgänge.
  • Parallelität und Wiederherstellung nach Abstürzen sind viel einfacher, wenn Segmentdateien anhängbar oder unveränderlich sind, z. B.: Machen Sie sich keine Sorgen über einen Absturz, wenn überschriebene Werte Dateien mit alten und neuen Werten hinterlassen.
  • Durch das Zusammenführen alter Segmente wird das Problem der Fragmentierung von Datendateien im Laufe der Zeit vermieden.

SSTables&LSM-Tree

Wenn die zu schreibenden Schlüssel geordnet angeordnet werden müssen, wird dieses Format zu einer sortierten Zeichenfolgentabelle, die als SSTable bezeichnet wird. Bei der Speichersortierung gibt es normalerweise Rot-Schwarz-Bäume oder AVL-Bäume.
Build-Prozess (LevelDB und RocksDB):

  • Schreiben Sie Daten und fügen Sie sie einem ausgeglichenen Baum im Speicher hinzu (z. B. einem Rot-Schwarz-Baum). Dieser speicherinterne Baum wird manchmal als Memtable bezeichnet.
  • Wenn der Speicher größer als ein bestimmter Schwellenwert ist (normalerweise einige Megabyte), wird er als SSTable-Datei auf die Festplatte geschrieben und kann gleichzeitig zu einer neuen Memtable-Instanz hinzugefügt werden.
  • Behandeln Sie die Leseanforderung, versuchen Sie einen Speicherabruf, dann die neueste Festplattensegmentdatei und durchlaufen Sie ein letztes Mal die anderen Dateien, bis das Ziel gefunden ist.
  • Der Hintergrundprozess führt in regelmäßigen Abständen eine Segmentzusammenführung und -komprimierung durch und verwirft überschriebene oder gelöschte Werte.
    Bei dem obigen Schema gibt es ein Problem: Wenn die Datenbank abstürzt, gehen die zuletzt geschriebenen Daten (in der Speichertabelle, aber nicht auf der Festplatte) verloren. Aus diesem Grund können Sie zunächst eine separate Datei auf der Festplatte behalten und Bei jedem Schreibvorgang wird das Protokoll angehängt und stürzt ab. Die Memtable kann dann wiederhergestellt werden. Immer wenn eine Memtable in SSTabl geschrieben wird, kann das entsprechende Protokoll verworfen werden.
    Die auf dem Dateiprinzip der Zusammenführung und Komprimierungssortierung basierende Speicher-Engine wird üblicherweise als LSM-Speicher-Engine bezeichnet

Leistungsoptimierung

  • Wenn Sie einen Schlüssel finden, der nicht existiert, kehren Sie immer zurück und greifen auf die alte Segmentdatei zu (Multiple Disk IO). Auf dieser Grundlage verwenden Speicher-Engines normalerweise Bloom-Filter.
  • LevelDB und RocksDB verwenden abgestufte Komprimierung, HBase verwendet Größenabstufung und Cassabdra unterstützt beide. Größeneinstufung: Neuere und kleinere SSTables werden sukzessive in ältere und größere SSTables zusammengeführt. Hierarchie: Ein Schlüsselbereich wird in mehrere kleinere SSTables aufgeteilt, wobei ältere auf separate „Ebenen“ verschoben werden.

B-Bäume

Es ist die Standard-Indeximplementierung fast aller relationalen Datenbanken, und viele nicht-relationale Datenbanken werden auch häufig verwendet. Die spezifischen Implementierungsdetails finden Sie in diesem Blog, den ich zuvor geschrieben habe: Das Prinzip der internen MySQL-Implementierung und -Optimierung
Um das Problem zu lösen, dass der Vorgang verschiedene Seiten abdecken muss und das Einfügen einen Seitenüberlauf verursacht, muss er aufgeteilt werden. Wenn zu diesem Zeitpunkt die Datenbank nach Abschluss des teilweisen Schreibens der Seite abstürzt, führt dies schließlich zu einer Indexbeschädigung. Da ein Write-Ahead-Log (WAL) hinzugefügt werden muss, wird es auch Redo-Log genannt. Es kann zusätzliche Änderungen unterstützen. Der B-Baum aktualisiert zuerst die WAL und ändert dann den Baum selbst. Wenn ein Absturz auftritt, kann er auf den neuesten konsistenten Zustand zurückgesetzt werden.

Leistungsoptimierung

  • Copy-on-Write: Anstatt WAL für die Wiederherstellung nach einem Absturz zu überschreiben und beizubehalten, verwenden einige Datenbanken geänderte Seiten, die an einen anderen Speicherort geschrieben werden, und eine neue Version der übergeordneten Seite im Baum wird erstellt und verweist auf den neuen Speicherort.
  • Durch das Speichern der Kurzinformationen des Schlüssels kann Platz gespart werden, und es können mehr Schlüssel auf die Seite verschoben werden, sodass der Baum einen höheren Verzweigungsfaktor aufweist und die Anzahl der Ebenen verringert (B+-Baum).
  • Einige B-Tree-Implementierungen legen den Baum so an, dass benachbarte Blattseiten nacheinander auf der Festplatte gespeichert werden, und die Aufrechterhaltung dieser Reihenfolge wird mit zunehmendem Baumwachstum immer schwieriger.
  • Durch das Hinzufügen zusätzlicher Zeiger zum Baum kann jede Blattseite auf andere Geschwisterseiten links und rechts verweisen, die nacheinander gescannt werden können (B+-Baum).

Verglichen

  • Der LSM-Baum ist beim Schreiben schneller und der B-Baum beim Lesen.
  • Der B-Baum schreibt Daten mindestens zweimal, einmal in das Write-Ahead-Protokoll und einmal in die Baumseite selbst (es können auch Seitenumbrüche auftreten).
  • Der Nachteil der Protokollspeicherung besteht darin, dass die Komprimierung die Lese- und Schreibvorgänge beeinträchtigt. Selbst wenn es sich um eine inkrementelle Komprimierung handelt, kann es aufgrund der begrenzten gleichzeitigen Ressourcen der Festplatte leicht sein, beim Komprimieren auf Lese- und Schreibanforderungen zu warten.
  • Wenn das Schreibvolumen hoch ist, die Komprimierung jedoch nicht mit der Geschwindigkeit mithalten kann, mit der neue Daten geschrieben werden, werden auf der Festplatte weiterhin nicht zusammengeführte Segmentdateien vorhanden sein, bis der Speicherplatz auf der Festplatte erschöpft ist.

andere Indizes

Der Primärschlüsselindex, der Sekundärindex, der Mehrspaltenindex, der Volltextindex und der Fuzzy-Index werden hier nicht beschrieben.

Transaktionsverarbeitung vs. analytische Verarbeitung

Transaktionen verfügen nicht unbedingt über ACID. Transaktionen bedeuten lediglich, dass Clients mit geringer Latenz lesen und schreiben können.
Dinge wie Blog-Kommentare, Spielaktionen, Adressbuchkontakte usw. werden als Online-Transaktionsverarbeitung (OLTP) bezeichnet.
Das Scannen einer großen Anzahl von Datensätzen wird wie die Datenanalyse als Online Analytical Processing (OLAP) bezeichnet.

Datenbank

Das Data Warehouse ist eine separate Datenbank, die Analysten verwenden können, ohne den OLTP-Betrieb zu beeinträchtigen, und alle Geschäfte sind Kopien von OLTP. Jedes große Unternehmen verfügt über ein Data Warehouse.
Data Warehouse und vereinfachter ETL-Prozess (Extract-Transform-Load):
Fügen Sie hier eine Bildbeschreibung ein

Schemata zur Stern- und Schneeflockenanalyse

Das Sternschema entsteht, wenn die Tabelle visualisiert wird. In der Mitte befindet sich die Faktentabelle, umgeben von einer Reihe von Dimensionstabellen, zum Beispiel: Persönlicher Blog, Kommentare, Likes, Browsing, Artikeltypen usw. werden alle gespeichert und verknüpft die Artikeltabelle. Eine Variation dieser Vorlage wird zum Schneeflockenschema, bei dem Dimensionen weiter in Unterräume unterteilt werden.

Säulenspeicher

Manchmal ist die in der Tabelle gespeicherte Datenmenge groß und es gibt viele Spalten. Wir fragen einige dieser Spalten gleichzeitig ab, aber in den meisten Datenbanken ist der Speicher zeilenorientiert angeordnet, sodass es notwendig ist, alle Zeilen von der Festplatte in den Speicher zu laden, sie zu analysieren und die Zeilen, die dies tun, zu filtern die Kriterien nicht erfüllen. **Das dauert lange.
Wenn die Spaltenspeicherung verwendet wird, werden alle Werte in jeder Spalte zusammen gespeichert, und jede Spalte wird in einer separaten Datei gespeichert, und die Abfrage muss nur die in der Abfrage verwendeten Spalten lesen und analysieren, was viel sparen kann arbeiten.

Spaltenkomprimierung

Die allgemeine Spaltenkomprimierung basiert auf der Bitmap-Komprimierung.
Fügen Sie hier eine Bildbeschreibung ein

Speicherbandbreite und Vektorisierung

Bei Data-Warehouse-Abfragen, die Millionen/Dutzende Millionen scannen, stellt die Bandbreite zum Laden der Daten von der Festplatte in den Speicher einen großen Engpass dar. Wir müssen überlegen, wie wir Speicherbandbreite für den CPU-Cache effizient zuweisen können, und durch die Spaltenkomprimierung können mehr Zeilen in der Spalte in den L1-Cache geladen werden.

Schreibvorgänge für den Spaltenspeicher

Derzeit wird LSM-Baum verwendet. Alle Schreibvorgänge werden zunächst in den Speicher eingegeben, der sortierten Struktur hinzugefügt und können dann auf die Festplatte geschrieben werden. Wenn sich genügend Schreibvorgänge angesammelt haben, werden sie mit der Spaltendatei auf der Festplatte zusammengeführt und stapelweise in eine neue Datei geschrieben. (Das kommerzielle Data Warehouse Vertica verfolgt diesen Ansatz)

Datenkodierung und -entwicklung

Im Entwicklungsprojekt kommt es häufig vor, dass sich das Upstream- und Downstream-Format oder sogar das logische Datenformat/-modus des eigenen Codes ändert. Zu diesem Zeitpunkt muss das Programm entsprechend angepasst werden (z. B. Hinzufügen von Feldern zum Datensatz, Programmlesen). Bei einem ausgereiften und riesigen System ist es nicht einfach, es zu aktualisieren und zu iterieren.

  • Für serverseitige Programme sind möglicherweise fortlaufende Upgrades (gestufte Bereitstellung) erforderlich. Die Bereitstellung erfolgt auf einer kleinen Anzahl von Knoten (oder wird als „großes Volumen“ bezeichnet). Überprüfen Sie, ob dies normal ist, und stellen Sie sie schrittweise vollständig bereit.
  • Für den Client kann er sich nur auf Benutzer-Upgrades verlassen.

Gleichzeitig bedeutet dies, dass alte und neue Codeversionen sowie neue und alte Datenformate gleichzeitig im System existieren können. Daher muss beim Entwerfen die Zwei-Wege-Kompatibilität gewahrt bleiben:
Abwärtskompatibilität: Neuerer Code kann von altem Code geschriebene Daten lesen.
Vorwärtskompatibilität: Alter Code kann Daten lesen, die von neuem Code geschrieben wurden.
Die Abwärtskompatibilität ist einfach, die Vorwärtskompatibilität erfordert, dass alter Code Ergänzungen neuerer Codeversionen ignoriert.

Datenkodierungsformat

Programme verfügen im Allgemeinen über mindestens zwei verschiedene Datendarstellungen:

  • Im Speicher werden Daten in Strukturen wie Objekten, Strukturen, Listen, Arrays, Hash-Tabellen und Bäumen gespeichert.
  • Wenn Daten in eine Datei geschrieben oder über das Netzwerk gesendet werden, müssen sie in eine Art eigenständige Bytefolge codiert werden.
    Die Konvertierung von der Speicherdarstellung in eine Bytesequenz wird zur Kodierung (Serialisierung), und der umgekehrte Prozess wird zur Dekodierung (Deserialisierung).

sprachspezifisches Format

Oftmals verfügt jede Programmiersprache über eine eigene Methode zum Codieren von Funktionen, auf die die andere Sprache nicht direkt zugreifen kann. Die Dekodierung wirft auch Sicherheitsbedenken auf.

JSON-, XML- und Binärvarianten

JSON, XML, einschließlich CSV sind allesamt Textformate, die gut lesbar sind. JSON unterscheidet zwischen Zeichenfolgen und Zahlen, nicht zwischen Ganzzahlen und Gleitkommazahlen, und gibt keine Genauigkeit an. Ganzzahlen größer als 2 hoch 53 können in Gleitkommazahlen mit doppelter Genauigkeit nach IEEE 754 nicht exakt dargestellt werden . Twitter verwendet die API, um JSON mit der Twitter-ID zweimal zurückzugeben, einmal eine JSON-Nummer und einmal eine Dezimalzeichenfolge, um das Problem zu lösen, dass JS die Nummer nicht richtig analysiert. Der Nachteil ist, dass es viel Platz einnimmt.
Die binäre Codierung ist klein und schnell im Netzwerk übertragen, was sich sehr gut für Szenarien mit großen Datenmengen eignet.

Thrift与Protokollpuffer

Thrift definiert das Datenformat:

struct Person {
    
    
	1: required string  userName,
	2: optional i64 age, 
}

Protokollpuffer definieren das Datenformat:

message Person {
    
    
	required string  user_name  = 1;
	optional int64  age         = 2, 
}

Wenn das Feld auf „erforderlich“ gesetzt ist, das Feld jedoch nicht ausgefüllt ist, schlägt die Ausführung zur Laufzeit fehl.

Avro

Es handelt sich um ein weiteres binäres Kodierungsformat, das einige interessante Unterschiede zu Protocol Buffers und Thrift aufweist. Avro startete 2009 als Hadoop-Teilprojekt.
Avro IDL (von Menschen bearbeitet):

record Persion {
    
    
	string userName;
	union {
    
    null, long}  favorite = null;
	array<string> interests;
}

Avro JSON-Formular:

{
	"type":"record",
	"name":"Person",
	"fields": [
		{"name":"userName",    "type": "sting"},
		{"name":"favorite",    "type": ["null", "sting"], "default": null},
		{"name":"interests",    "type": {"type", "array", "items": "string"}},
	]
}

Vorteile der Definition eines Datenschemas:

  • Sie sind kompakter als die verschiedenen „binären JSON“-Varianten und können Feldnamen in den codierten Daten weglassen.
  • Schemata sind eine wertvolle Form der Dokumentation, da für die Dekodierung Schemata erforderlich sind, sodass Sie sicher sein können, dass sie auf dem neuesten Stand sind.
  • Die Schemadatenbank ermöglicht die Überprüfung von Schemaänderungen auf Vorwärts- und Abwärtskompatibilität, bevor etwas bereitgestellt wird.
  • Für statisch typisierte Sprachen ist die Möglichkeit, Code aus Schemata zu generieren, nützlich und ermöglicht die Typprüfung zur Kompilierungszeit.

Datenflussmodus

Daten können auf verschiedene Weise von einem Prozess zum anderen fließen. Gängige Datenflussmethoden:

  • Datenbank
  • Serviceaufrufe (REST und RPC)
  • asynchrone Nachrichtenübermittlung

AUSRUHEN

REST ist kein Protokoll, sondern eine Designphilosophie, die auf den Prinzipien von HTTP basiert. Es legt Wert auf einfache Datenformate, verwendet URLs zur Identifizierung von Ressourcen und nutzt HTTP-Funktionen für die Cache-Steuerung, Authentifizierung und Inhaltstyp-Aushandlung.

SEIFE

Es basiert auf dem XML-Protokoll zum Senden von Web-API-Anfragen.

Messaging (RabbitMQ, ActiveMQ, HornetQ, NATS, Kafka)

Einfach ausgedrückt wird der Client mit geringer Latenz an einen anderen Prozess übergeben.
Vorteil:

  • Es kann als Cache-Bereich fungieren, Spitzen glätten und die Systemverfügbarkeit erhöhen.
  • Es kann automatisch Nachrichten an abgestürzte Prozesse senden und so den Verlust von Nachrichten verhindern.
  • Dadurch entfällt die Notwendigkeit, dass der Sender die IP-Adresse und Portnummer des Empfängers kennt
  • Es unterstützt das Senden einer Nachricht an mehrere Empfänger.
  • Die Trennung von Sender und Empfänger wird realisiert.

Das Obige ist eine kurze Zusammenfassung des Speichersystems.

Ich denke du magst

Origin blog.csdn.net/weixin_43885417/article/details/130471848
Empfohlen
Rangfolge