Verwendung
Mit der vereinheitlichten Batch- und Stream-Verarbeitung und der Cloud-nativen Architektur stellt Milvus 2.0 eine größere Herausforderung dar als sein Vorgänger bei der Entwicklung der DELETE-Funktion. Dank des fortschrittlichen Disaggregationsdesigns für die Speicherberechnung und des flexiblen Veröffentlichungs-/Abonnement-Mechanismus können wir mit Stolz verkünden, dass wir es geschafft haben. In Milvus 2.0 können Sie eine Entität in einer bestimmten Sammlung mit ihrem Primärschlüssel löschen, so dass die gelöschte Entität nicht mehr im Ergebnis einer Suche oder einer Abfrage aufgeführt wird.
Bitte beachten Sie, dass sich die DELETE-Operation in Milvus auf die logische Löschung bezieht, während die physische Datenbereinigung während der Datenverdichtung stattfindet. Logisches Löschen erhöht nicht nur die durch die E/A-Geschwindigkeit eingeschränkte Suchleistung, sondern erleichtert auch die Datenwiederherstellung. Logisch gelöschte Daten können mit Hilfe der Zeitreisefunktion wiederhergestellt werden.
Verwendung
Lassen Sie uns zunächst die DELETE-Funktion in Milvus 2.0 ausprobieren. (Das folgende Beispiel verwendet PyMilvus 2.0.0 auf Milvus 2.0.0).
from pymilvus import connections, utility, Collection, DataType, FieldSchema, CollectionSchema
# Connect to Milvus
connections.connect(
alias="default",
host='x.x.x.x',
port='19530'
)
# Create a collection with Strong Consistency level
pk_field = FieldSchema(
name="id",
dtype=DataType.INT64,
is_primary=True,
)
vector_field = FieldSchema(
name="vector",
dtype=DataType.FLOAT_VECTOR,
dim=2
)
schema = CollectionSchema(
fields=[pk_field, vector_field],
description="Test delete"
)
collection_name = "test_delete"
collection = Collection(
name=collection_name,
schema=schema,
using='default',
shards_num=2,
consistency_level="Strong"
)
# Insert randomly generated vectors
import random
data = [
[i for i in range(100)],
[[random.random() for _ in range(2)] for _ in range(100)],
]
collection.insert(data)
# Query to make sure the entities to delete exist
collection.load()
expr = "id in [2,4,6,8,10]"
pre_del_res = collection.query(
expr,
output_fields = ["id", "vector"]
)
print(pre_del_res)
# Delete the entities with the previous expression
collection.delete(expr)
# Query again to check if the deleted entities exist
post_del_res = collection.query(
expr,
output_fields = ["id", "vector"]
)
print(post_del_res)
Implementierung
In einer Milvus-Instanz ist ein Datenknoten hauptsächlich dafür verantwortlich, Streaming-Daten (Logs im Log-Broker) als historische Daten (Log-Snapshots) zu packen und automatisch in den Objektspeicher zu flushen. Ein Abfrageknoten führt Suchanfragen auf vollständigen Daten aus, d. h. sowohl auf Streaming-Daten als auch auf historischen Daten.
Um die Datenschreibkapazitäten der parallelen Knoten in einem Cluster optimal zu nutzen, verwendet Milvus eine Sharding-Strategie, die auf Primärschlüssel-Hashing basiert, um die Schreibvorgänge gleichmäßig auf verschiedene Arbeitsknoten zu verteilen. Das heißt, dass der Proxy die DML-Nachrichten (d.h. Anfragen) einer Entität an denselben Daten- und Abfrageknoten weiterleitet. Diese Nachrichten werden über den DML-Kanal veröffentlicht und von dem Datenknoten und dem Abfrageknoten getrennt konsumiert, um Such- und Abfragedienste gemeinsam bereitzustellen.
Datenknoten
Nach dem Empfang von INSERT-Nachrichten fügt der Datenknoten die Daten in ein wachsendes Segment ein, d. h. in ein neues Segment, das für den Empfang von Streaming-Daten im Speicher erstellt wird. Wenn entweder die Anzahl der Datenzeilen oder die Dauer des wachsenden Segments den Schwellenwert erreicht, versiegelt der Datenknoten es, um weitere eingehende Daten zu verhindern. Der Datenknoten spült dann das versiegelte Segment, das die historischen Daten enthält, in den Objektspeicher. In der Zwischenzeit generiert der Datenknoten einen Bloomfilter auf der Grundlage der Primärschlüssel der neuen Daten und spült ihn zusammen mit dem versiegelten Segment in den Objektspeicher, wobei er den Bloomfilter als Teil des binären Statistikprotokolls (binlog) speichert, das die statistischen Informationen des Segments enthält.
Ein Bloomfilter ist eine probabilistische Datenstruktur, die aus einem langen binären Vektor und einer Reihe von Zufallsabbildungsfunktionen besteht. Er kann verwendet werden, um zu testen, ob ein Element Mitglied einer Menge ist, kann aber auch falsch positive Treffer liefern. -- Wikipedia
Wenn Daten-DELETE-Nachrichten eingehen, puffert der Datenknoten alle Bloom-Filter im entsprechenden Shard und gleicht sie mit den in den Nachrichten angegebenen Primärschlüsseln ab, um alle Segmente (sowohl die wachsenden als auch die versiegelten) abzurufen, die möglicherweise die zu löschenden Entitäten enthalten. Nachdem die entsprechenden Segmente lokalisiert wurden, puffert der Datenknoten sie im Speicher, um die Delta-Binlogs zur Aufzeichnung der Löschvorgänge zu erzeugen, und spült diese Binlogs dann zusammen mit den Segmenten zurück in den Objektspeicher.
Datenknoten
Da einem Shard nur ein DML-Kanal zugewiesen ist, können zusätzliche Abfrageknoten, die dem Cluster hinzugefügt werden, den DML-Kanal nicht abonnieren. Um sicherzustellen, dass alle Abfrageknoten die DELETE-Nachrichten empfangen können, filtern die Datenknoten die DELETE-Nachrichten aus dem DML-Kanal und leiten sie an den Delta-Kanal weiter, um alle Abfrageknoten über die Löschvorgänge zu informieren.
Abfrageknoten
Beim Laden einer Sammlung aus dem Objektspeicher holt sich der Abfrageknoten zunächst den Prüfpunkt jedes Shards, der die DML-Vorgänge seit dem letzten Flush-Vorgang markiert. Auf der Grundlage des Prüfpunkts lädt der Abfrageknoten alle versiegelten Segmente zusammen mit ihren Delta-Binlog- und Bloom-Filtern. Wenn alle Daten geladen sind, abonniert der Abfrageknoten DML-Channel, Delta-Channel und Query-Channel.
Wenn weitere INSERT-Nachrichten eintreffen, nachdem die Sammlung in den Speicher geladen wurde, bestimmt der Abfrageknoten zunächst die wachsenden Segmente entsprechend den Nachrichten und aktualisiert die entsprechenden Bloomfilter im Speicher nur für Abfragezwecke. Diese für die Abfrage bestimmten Bloomfilter werden nach Abschluss der Abfrage nicht in den Objektspeicher gespült.
Abfrageknoten
Wie oben erwähnt, kann nur eine bestimmte Anzahl von Abfrageknoten DELETE-Nachrichten vom DML-Kanal empfangen, d.h. nur sie können die DELETE-Anfragen in wachsenden Segmenten ausführen. Diejenigen Abfrageknoten, die den DML-Kanal abonniert haben, filtern zunächst die DELETE-Nachrichten in den wachsenden Segmenten, suchen die Entitäten, indem sie die bereitgestellten Primärschlüssel mit den abfragespezifischen Bloomfiltern der wachsenden Segmente abgleichen, und zeichnen dann die Löschvorgänge in den entsprechenden Segmenten auf.
Abfrageknoten, die den DML-Kanal nicht abonnieren können, dürfen nur Such- oder Abfrageanfragen auf versiegelten Segmenten verarbeiten, da sie nur den Delta-Kanal abonnieren und die von Datenknoten weitergeleiteten DELETE-Nachrichten empfangen können. Nachdem die Abfrageknoten alle DELETE-Nachrichten in den versiegelten Segmenten des Delta-Kanals gesammelt haben, lokalisieren sie die Entitäten, indem sie die angegebenen Primärschlüssel mit den Bloom-Filtern der versiegelten Segmente abgleichen, und zeichnen dann die Löschvorgänge in den entsprechenden Segmenten auf.
Schließlich generieren die Abfrageknoten bei einer Suche oder Abfrage ein Bitset auf der Grundlage der Löschaufzeichnungen, um die gelöschten Entitäten auszulassen, und suchen unter den verbleibenden Entitäten aus allen Segmenten, unabhängig vom Segmentstatus. Nicht zuletzt beeinflusst die Konsistenzstufe die Sichtbarkeit der gelöschten Daten. Unter Strong Consistency Level (wie im vorherigen Codebeispiel gezeigt) sind die gelöschten Entitäten sofort nach dem Löschen unsichtbar. Bei Bounded Consistency Level dauert es mehrere Sekunden, bis die gelöschten Objekte unsichtbar werden.
Was kommt als Nächstes?
In der Blogserie zu den neuen Funktionen 2.0 wollen wir das Design der neuen Funktionen erklären. Lesen Sie mehr in dieser Blogserie!
- Implementierung
- Was kommt als Nächstes?
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word