🚀 Testen Sie Zilliz Cloud, die vollständig verwaltete Milvus, kostenlos – erleben Sie 10x schnellere Leistung! Jetzt testen>>

milvus-logo
LFAI
  • Home
  • Blog
  • Dateneinfügung und Datenpersistenz in einer Vektordatenbank

Dateneinfügung und Datenpersistenz in einer Vektordatenbank

  • Engineering
April 06, 2022
Bingyi Sun

Cover image Titelbild

Dieser Artikel wurde von Bingyi Sun geschrieben und von Angela Ni umgesetzt.

Im letzten Beitrag der Deep Dive-Serie haben wir vorgestellt , wie Daten in Milvus, der weltweit fortschrittlichsten Vektordatenbank, verarbeitet werden. In diesem Artikel werden wir weiterhin die Komponenten untersuchen, die an der Dateneinfügung beteiligt sind, das Datenmodell im Detail illustrieren und erklären, wie die Datenpersistenz in Milvus erreicht wird.

Springe zu:

Wiederholung der Milvus-Architektur

Milvus architecture. Milvus-Architektur.

SDK sendet Datenanfragen an den Proxy, das Portal, über den Load Balancer. Dann interagiert der Proxy mit dem Coordinator Service, um DDL- (Data Definition Language) und DML- (Data Manipulation Language) Anfragen in den Nachrichtenspeicher zu schreiben.

Arbeiterknoten, einschließlich Abfrageknoten, Datenknoten und Indexknoten, nehmen die Anforderungen aus dem Nachrichtenspeicher entgegen. Der Abfrageknoten ist für die Datenabfrage zuständig, der Datenknoten für die Dateneinfügung und die Datenpersistenz, und der Indexknoten befasst sich hauptsächlich mit der Indexerstellung und der Abfragebeschleunigung.

Die unterste Schicht ist der Objektspeicher, der hauptsächlich MinIO, S3 und AzureBlob für die Speicherung von Protokollen, Delta-Binlogs und Indexdateien nutzt.

Das Portal für Dateneinfügeanfragen

Proxy in Milvus. Proxy in Milvus.

Proxy dient als Portal für Dateneinfügeanfragen.

  1. Zunächst nimmt der Proxy Dateneinfügeanfragen von SDKs entgegen und teilt diese Anfragen mithilfe eines Hash-Algorithmus in mehrere Buckets ein.
  2. Dann fordert der Proxy die Datenkoordinatoren auf, Segmente zuzuweisen, die kleinste Einheit in Milvus für die Datenspeicherung.
  3. Anschließend fügt der Proxy die Informationen über die angeforderten Segmente in den Nachrichtenspeicher ein, damit diese Informationen nicht verloren gehen.

Datenkoordinaten und Datenknoten

Die Hauptfunktion des Datenkoordinators ist die Verwaltung der Kanal- und Segmentzuweisung, während die Hauptfunktion des Datenknotens darin besteht, die eingefügten Daten zu verbrauchen und aufzubewahren.

Data coord and data node in Milvus. Datenkoordinator und Datenknoten in Milvus.

Funktion

Die Datenkoordinierung hat die folgenden Aufgaben:

  • Zuweisung von SegmentplatzDie Datenkoordination weist dem Proxy Platz in wachsenden Segmenten zu, so dass der Proxy freien Platz in den Segmenten zum Einfügen von Daten nutzen kann.

  • Aufzeichnung der Segmentzuweisung und des Verfallszeitpunkts des zugewiesenen Platzes im SegmentDer vom Data Coord zugewiesene Platz in jedem Segment ist nicht dauerhaft, daher muss das Data Coord auch den Verfallszeitpunkt jeder Segmentzuweisung aufzeichnen.

  • Automatisches Flushen von SegmentdatenWenn das Segment voll ist, löst das Datenkoordinatensystem automatisch ein Flushen der Daten aus.

  • Zuweisung von Kanälen an DatenknotenEine Sammlung kann mehrere V-Kanäle haben. Die Datenkoordination legt fest, welche V-Kanäle von welchen Datenknoten verbraucht werden.

Datenknoten haben die folgenden Aufgaben:

  • Daten konsumierenDer Datenknoten konsumiert Daten aus den von der Datenkoordinierung zugewiesenen Kanälen und erstellt eine Sequenz für die Daten.

  • DatenpersistenzZwischenspeichern der eingefügten Daten im Speicher und automatisches Auslagern der eingefügten Daten auf die Festplatte, wenn das Datenvolumen einen bestimmten Schwellenwert erreicht.

Arbeitsablauf

One vchannel can only be assigned to one data node. Ein vchannel kann nur einem Datenknoten zugewiesen werden.

Wie in der obigen Abbildung zu sehen ist, hat die Sammlung vier V-Kanäle (V1, V2, V3 und V4) und es gibt zwei Datenknoten. Es ist sehr wahrscheinlich, dass die Datenkoordination einem Datenknoten die Daten von V1 und V2 zuweist und dem anderen Datenknoten die Daten von V3 und V4. Ein einziger V-Kanal kann nicht mehreren Datenknoten zugewiesen werden, um eine Wiederholung des Datenverbrauchs zu verhindern, der sonst dazu führen würde, dass derselbe Datenstapel wiederholt in dasselbe Segment eingefügt wird.

Wurzelkoordinate und Zeittick

Root Coord verwaltet TSO (Timestamp Oracle) und veröffentlicht weltweit Zeittick-Meldungen. Jede Dateneinfügeanforderung hat einen von Root Coord zugewiesenen Zeitstempel. Time Tick ist der Eckpfeiler von Milvus, der wie eine Uhr in Milvus funktioniert und angibt, zu welchem Zeitpunkt sich das Milvus-System befindet.

Wenn Daten in Milvus geschrieben werden, trägt jede Dateneinfügeanfrage einen Zeitstempel. Während des Datenkonsums konsumiert jeder Zeitdatenknoten Daten, deren Zeitstempel innerhalb eines bestimmten Bereichs liegen.

An example of data insertion and data consumption based on timestamp. Ein Beispiel für Dateneinfügung und Datenverbrauch auf der Grundlage von Zeitstempeln.

Die obige Abbildung zeigt den Prozess des Einfügens von Daten. Die Werte der Zeitstempel werden durch die Zahlen 1,2,6,5,7,8 dargestellt. Die Daten werden von zwei Proxys in das System geschrieben: p1 und p2. Wenn während des Datenverbrauchs die aktuelle Zeit des Zeitticks 5 ist, können die Datenknoten nur die Daten 1 und 2 lesen. Wenn die aktuelle Zeit des Time Tick 9 ist, können die Daten 6, 7 und 8 von den Datenknoten gelesen werden.

Datenorganisation: Sammlung, Partition, Scherbe (Kanal), Segment

Data organization in Milvus. Datenorganisation in Milvus.

Lesen Sie zunächst diesen Artikel, um das Datenmodell in Milvus und die Konzepte von Sammlung, Scherbe, Partition und Segment zu verstehen.

Zusammenfassend lässt sich sagen, dass die größte Dateneinheit in Milvus eine Sammlung ist, die mit einer Tabelle in einer relationalen Datenbank verglichen werden kann. Eine Sammlung kann mehrere Scherben (die jeweils einem Kanal entsprechen) und mehrere Partitionen innerhalb jeder Scherbe haben. Wie in der obigen Abbildung dargestellt, sind die Kanäle (Shards) die vertikalen Balken, während die Partitionen die horizontalen Balken sind. An jedem Schnittpunkt befindet sich das Konzept des Segments, die kleinste Einheit für die Datenzuweisung. In Milvus werden Indizes auf Segmenten aufgebaut. Während einer Abfrage gleicht das Milvus-System auch die Abfragelast in den verschiedenen Abfrageknoten aus, und dieser Prozess wird auf der Grundlage der Einheit der Segmente durchgeführt. Segmente enthalten mehrere binlogs, und wenn die Segmentdaten verbraucht sind, wird eine binlog-Datei erzeugt.

Segment

In Milvus gibt es drei Arten von Segmenten mit unterschiedlichem Status: wachsende, versiegelte und geleerte Segmente.

Wachsendes Segment

Ein wachsendes Segment ist ein neu erstelltes Segment, das dem Proxy zum Einfügen von Daten zugewiesen werden kann. Der interne Speicherplatz eines Segments kann verwendet, zugewiesen oder frei sein.

Three status in a growing segment Drei Status in einem wachsenden Segment

  • Belegt: Dieser Teil des Speicherplatzes eines wachsenden Segments wurde von einem Datenknoten verbraucht.
  • Zugewiesen: Dieser Teil des Speicherplatzes eines wachsenden Segments wurde vom Proxy angefordert und von der Datenkoordinate zugewiesen. Der zugewiesene Speicherplatz läuft nach einer bestimmten Zeitspanne ab.
  • Frei: Dieser Teil des Speicherplatzes eines wachsenden Segments wurde noch nicht verwendet. Der Wert des freien Speicherplatzes entspricht dem Gesamtspeicherplatz des Segments abzüglich des Wertes des verwendeten und zugewiesenen Speicherplatzes. Der freie Speicherplatz eines Segments nimmt also zu, wenn der zugewiesene Speicherplatz abläuft.

Versiegeltes Segment

Ein versiegeltes Segment ist ein geschlossenes Segment, das dem Proxy nicht mehr zur Dateneinfügung zugewiesen werden kann.

Sealed segment in Milvus Versiegeltes Segment in Milvus

Ein wachsendes Segment wird unter den folgenden Umständen versiegelt:

  • Wenn der belegte Platz in einem wachsenden Segment 75% des gesamten Platzes erreicht, wird das Segment versiegelt.
  • Flush() wird manuell von einem Milvus-Benutzer aufgerufen, um alle Daten in einer Sammlung zu erhalten.
  • Wachsende Segmente, die nach einem langen Zeitraum nicht versiegelt sind, werden versiegelt, da zu viele wachsende Segmente dazu führen, dass die Datenknoten zu viel Speicher verbrauchen.

Gespültes Segment

Ein Flush-Segment ist ein Segment, das bereits auf die Festplatte geschrieben wurde. Flush bezieht sich auf die Speicherung von Segmentdaten im Objektspeicher zum Zwecke der Datenpersistenz. Ein Segment kann nur geflusht werden, wenn der zugewiesene Speicherplatz in einem versiegelten Segment abläuft. Beim Flushen wird das versiegelte Segment in ein geflushtes Segment umgewandelt.

Flushed segment in Milvus Gespültes Segment in Milvus

Kanal

Ein Kanal wird zugewiesen:

  • Wenn ein Datenknoten gestartet oder heruntergefahren wird; oder
  • wenn der zugewiesene Segmentplatz vom Proxy angefordert wird.

Dann gibt es mehrere Strategien der Kanalzuweisung. Milvus unterstützt 2 dieser Strategien:

  1. Konsistentes Hashing

Consistency hashing in Milvus Konsistentes Hashing in Milvus

Die Standardstrategie in Milvus. Diese Strategie nutzt die Hashing-Technik, um jedem Kanal eine Position auf dem Ring zuzuweisen, und sucht dann im Uhrzeigersinn nach dem nächstgelegenen Datenknoten für einen Kanal. In der obigen Abbildung wird also Kanal 1 dem Datenknoten 2 und Kanal 2 dem Datenknoten 3 zugewiesen.

Ein Problem bei dieser Strategie ist jedoch, dass die Erhöhung oder Verringerung der Anzahl der Datenknoten (z. B. wenn ein neuer Datenknoten hinzukommt oder ein Datenknoten plötzlich abgeschaltet wird) den Prozess der Kanalzuweisung beeinflussen kann. Um dieses Problem zu lösen, überwacht data coord den Status der Datenknoten über etcd, so dass data coord sofort benachrichtigt werden kann, wenn sich der Status der Datenknoten ändert. Dann bestimmt data coord, welchem Datenknoten die Kanäle ordnungsgemäß zugewiesen werden sollen.

  1. Lastausgleich

Die zweite Strategie besteht darin, Kanäle derselben Sammlung verschiedenen Datenknoten zuzuweisen, um sicherzustellen, dass die Kanäle gleichmäßig zugewiesen werden. Der Zweck dieser Strategie ist es, einen Lastausgleich zu erreichen.

Datenzuweisung: wann und wie

The process of data allocation in Milvus Der Prozess der Datenzuweisung in Milvus

Der Prozess der Datenzuweisung beginnt beim Client. Er sendet zunächst Dateneinfügeanfragen mit einem Zeitstempel t1 an den Proxy. Dann sendet der Proxy eine Anfrage an die Datenkoordination zur Segmentzuweisung.

Nach Erhalt der Segmentzuweisungsanforderung prüft die Datenkoordination den Segmentstatus und weist das Segment zu. Wenn der aktuelle Speicherplatz der erstellten Segmente für die neu eingefügten Datenzeilen ausreicht, weist die Datenkoordination diese erstellten Segmente zu. Reicht der in den aktuellen Segmenten verfügbare Platz jedoch nicht aus, weist das Datenkoordinator ein neues Segment zu. Die Datenkoordinierungsstelle kann bei jeder Anfrage ein oder mehrere Segmente zurückgeben. In der Zwischenzeit speichert das Datenkoordinatensystem auch das zugewiesene Segment im Metaserver für die Datenpersistenz.

Anschließend gibt das Datenkoordinatensystem die Informationen über das zugewiesene Segment (einschließlich Segment-ID, Anzahl der Zeilen, Ablaufzeit t2 usw.) an den Proxy zurück. Der Proxy sendet diese Informationen über das zugewiesene Segment an den Nachrichtenspeicher, damit diese Informationen ordnungsgemäß aufgezeichnet werden. Beachten Sie, dass der Wert von t1 kleiner sein muss als der von t2. Der Standardwert von t2 beträgt 2.000 Millisekunden und kann durch Konfiguration des Parameters segment.assignmentExpiration in der Datei data_coord.yaml geändert werden.

Binlog-Dateistruktur und Datenpersistenz

Data node flush Datenknoten Flush

Der Datenknoten abonniert den Nachrichtenspeicher, da Dateneinfügeanforderungen im Nachrichtenspeicher aufbewahrt werden und die Datenknoten somit Einfügemeldungen konsumieren können. Die Datenknoten legen Einfügeaufträge zunächst in einem Einfügepuffer ab, und wenn sich die Aufträge ansammeln, werden sie nach Erreichen eines Schwellenwerts in den Objektspeicher gespült.

Struktur der Binlog-Datei

Binlog file structure. Binlog-Dateistruktur.

Die Struktur der Binlog-Datei in Milvus ähnelt der in MySQL. Binlog wird für zwei Funktionen verwendet: Datenwiederherstellung und Indexerstellung.

Ein Binlog enthält viele Ereignisse. Jedes Ereignis hat einen Ereigniskopf und Ereignisdaten.

Metadaten wie die Erstellungszeit des Binlogs, die ID des Schreibknotens, die Länge des Ereignisses und NextPosition (Offset des nächsten Ereignisses) usw. werden in den Ereigniskopf geschrieben.

Die Ereignisdaten können in zwei Teile unterteilt werden: fest und variabel.

File structure of an insert event. Dateistruktur eines Einfügeereignisses.

Der feste Teil in den Ereignisdaten eines INSERT_EVENT enthält StartTimestamp, EndTimestamp und reserved.

Der variable Teil speichert die eingefügten Daten. Die Einfügedaten werden in das Format von Parquet sequenziert und in dieser Datei gespeichert.

Persistenz der Daten

Wenn es mehrere Spalten im Schema gibt, speichert Milvus Binlogs in Spalten.

Binlog data persistence. Persistenz der Binlog-Daten.

Wie in der Abbildung oben dargestellt, ist die erste Spalte der Primärschlüssel binlog. Die zweite ist eine Zeitstempelspalte. Der Rest sind die im Schema definierten Spalten. Der Dateipfad der Binlogs in MinIO ist ebenfalls in der obigen Abbildung angegeben.

Über die Deep Dive-Serie

Mit der offiziellen Ankündigung der allgemeinen Verfügbarkeit von Milvus 2.0 haben wir diese Milvus-Deep-Dive-Blogserie ins Leben gerufen, um eine tiefgehende Interpretation der Milvus-Architektur und des Quellcodes zu bieten. Die Themen dieser Blogserie umfassen:

Like the article? Spread the word

Weiterlesen