Insertion et persistance des données dans une base de données vectorielle
Image de couverture
Cet article a été rédigé par Bingyi Sun et transcrit par Angela Ni.
Dans le précédent article de la série Deep Dive, nous avons présenté la manière dont les données sont traitées dans Milvus, la base de données vectorielles la plus avancée au monde. Dans cet article, nous continuerons à examiner les composants impliqués dans l'insertion des données, nous illustrerons le modèle de données en détail et nous expliquerons comment la persistance des données est réalisée dans Milvus.
Aller à :
- Récapitulatif de l'architecture de Milvus
- Le portail des demandes d'insertion de données
- Coordonnée des données et nœud de données
- Coordonnée racine et Time Tick
- Organisation des données : collecte, partition, tesson (canal), segment
- Allocation des données : quand et comment
- Structure du fichier Binlog et persistance des données
Récapitulatif de l'architecture Milvus
Architecture Milvus.
Le SDK envoie des demandes de données au proxy, le portail, via l'équilibreur de charge. Le proxy interagit ensuite avec le service de coordination pour écrire les requêtes DDL (langage de définition des données) et DML (langage de manipulation des données) dans le stockage des messages.
Les nœuds de travail, y compris le nœud de requête, le nœud de données et le nœud d'index, consomment les requêtes à partir du stockage de messages. Plus précisément, le nœud d'interrogation est chargé de l'interrogation des données ; le nœud de données est responsable de l'insertion et de la persistance des données ; et le nœud d'indexation s'occupe principalement de la création d'index et de l'accélération des requêtes.
La couche inférieure est le stockage d'objets, qui exploite principalement MinIO, S3 et AzureBlob pour stocker les journaux, les binlogs delta et les fichiers d'index.
Le portail des demandes d'insertion de données
Proxy dans Milvus.
Le proxy sert de portail pour les demandes d'insertion de données.
- Au départ, le proxy accepte les demandes d'insertion de données des SDK et répartit ces demandes dans plusieurs buckets à l'aide d'un algorithme de hachage.
- Ensuite, le proxy demande à la coordination des données d'attribuer des segments, la plus petite unité de Milvus pour le stockage des données.
- Ensuite, le proxy insère les informations des segments demandés dans le magasin de messages afin que ces informations ne soient pas perdues.
Coordonnée des données et nœud de données
La fonction principale de la coordination des données est de gérer l'attribution des canaux et des segments, tandis que la fonction principale du nœud de données est de consommer et de conserver les données insérées.
Coordonnée des données et nœud de données dans Milvus.
Fonction
Le coordonnateur de données remplit les fonctions suivantes :
Allocation de l'espace des segmentsLa coordination des données alloue au proxy l'espace des segments croissants afin que le proxy puisse utiliser l'espace libre des segments pour insérer des données.
Enregistrer l'allocation de segments et l'heure d'expiration de l'espace alloué dans le segmentL'espace dans chaque segment alloué par la coordonnée des données n'est pas permanent, c'est pourquoi la coordonnée des données doit également enregistrer l'heure d'expiration de chaque allocation de segment.
Vider automatiquement les données du segmentSi le segment est plein, la coordination des données déclenche automatiquement le vidage des données.
Attribuer des canaux aux nœuds de donnéesUne collection peut avoir plusieurs canaux virtuels. La coordination des données détermine quels canaux sont consommés par quels nœuds de données.
Les nœuds de données remplissent les fonctions suivantes :
Consommation des donnéesLe nœud de données consomme les données des canaux alloués par la coordination des données et crée une séquence pour les données.
Persistance des donnéesLe nœud de données met en cache les données insérées dans la mémoire et les transfère automatiquement sur le disque lorsque le volume de données atteint un certain seuil.
Flux de travail
Un canal virtuel ne peut être attribué qu'à un seul nœud de données.
Comme le montre l'image ci-dessus, la collection comporte quatre canaux virtuels (V1, V2, V3 et V4) et deux nœuds de données. Il est très probable que la coordination des données affecte un nœud de données à la consommation des données de V1 et V2, et l'autre nœud de données à la consommation des données de V3 et V4. Un seul canal virtuel ne peut pas être attribué à plusieurs nœuds de données afin d'éviter la répétition de la consommation de données, qui entraînerait l'insertion répétée du même lot de données dans le même segment.
Root coord et Time Tick
Root coord gère TSO (timestamp Oracle) et publie des messages Time Tick à l'échelle mondiale. Chaque demande d'insertion de données est assortie d'un horodatage attribué par le coordonnateur principal. Le Time Tick est la pierre angulaire de Milvus. Il agit comme une horloge dans Milvus et indique à quel moment le système Milvus se trouve.
Lorsque des données sont écrites dans Milvus, chaque demande d'insertion de données porte un horodatage. Lors de la consommation des données, chaque nœud de données temporelles consomme des données dont l'horodatage se situe dans une certaine fourchette.
Exemple d'insertion et de consommation de données basées sur l'horodatage.
L'image ci-dessus représente le processus d'insertion de données. Les valeurs des horodatages sont représentées par les nombres 1, 2, 6, 5, 7 et 8. Les données sont écrites dans le système par deux mandataires : p1 et p2. Lors de la consommation des données, si l'heure actuelle du Time Tick est 5, les nœuds de données ne peuvent lire que les données 1 et 2. Lors de la deuxième lecture, si l'heure actuelle du Time Tick est 9, les données 6, 7 et 8 peuvent être lues par le nœud de données.
Organisation des données : collection, partition, shard (canal), segment
Organisation des données dans Milvus.
Lisez d'abord cet article pour comprendre le modèle de données dans Milvus et les concepts de collection, de partition et de segment.
En résumé, la plus grande unité de données dans Milvus est une collection qui peut être comparée à une table dans une base de données relationnelle. Une collection peut avoir plusieurs niveaux (chacun correspondant à un canal) et plusieurs partitions à l'intérieur de chaque niveau. Comme le montre l'illustration ci-dessus, les canaux (shards) sont les barres verticales tandis que les partitions sont les barres horizontales. À chaque intersection se trouve le concept de segment, la plus petite unité d'allocation de données. Dans Milvus, les index sont construits sur des segments. Au cours d'une interrogation, le système Milvus équilibre également les charges d'interrogation dans différents nœuds d'interrogation et ce processus est mené sur la base de l'unité des segments. Les segments contiennent plusieurs binlogs, et lorsque les données du segment sont consommées, un fichier binlog est généré.
Segment
Il existe trois types de segments avec des statuts différents dans Milvus : le segment croissant, le segment scellé et le segment effacé.
Segment en croissance
Un segment croissant est un segment nouvellement créé qui peut être alloué au proxy pour l'insertion de données. L'espace interne d'un segment peut être utilisé, alloué ou libre.
Trois états dans un segment croissant
- Utilisé : cette partie de l'espace d'un segment croissant a été consommée par un nœud de données.
- Alloué : cette partie de l'espace d'un segment croissant a été demandée par le proxy et allouée par le coordonnateur des données. L'espace alloué expirera après un certain temps.
- Libre : cette partie de l'espace d'un segment croissant n'a pas été utilisée. La valeur de l'espace libre est égale à l'espace total du segment soustrait de la valeur de l'espace utilisé et alloué. L'espace libre d'un segment augmente donc au fur et à mesure que l'espace alloué expire.
Segment scellé
Un segment scellé est un segment fermé qui ne peut plus être alloué au proxy pour l'insertion de données.
Segment scellé dans Milvus
Un segment croissant est scellé dans les circonstances suivantes :
- Si l'espace utilisé dans un segment croissant atteint 75 % de l'espace total, le segment sera scellé.
- Flush() est appelé manuellement par un utilisateur de Milvus pour conserver toutes les données d'une collection.
- Les segments en croissance qui ne sont pas scellés après une longue période seront scellés, car un trop grand nombre de segments en croissance entraîne une surconsommation de mémoire par les nœuds de données.
Segment effacé
Un segment effacé est un segment qui a déjà été écrit sur le disque. Le terme "flush" fait référence au stockage des données d'un segment dans un système de stockage d'objets à des fins de persistance des données. Un segment ne peut être effacé que lorsque l'espace alloué dans un segment scellé expire. Lorsqu'il est effacé, le segment scellé devient un segment effacé.
Segment effacé dans Milvus
Canal
Un canal est alloué :
- lorsque le nœud de données démarre ou s'arrête ; ou
- lorsque l'espace du segment alloué est demandé par le proxy.
Il existe ensuite plusieurs stratégies d'attribution des canaux. Milvus prend en charge deux de ces stratégies :
- Hachage cohérent
Hachage cohérent dans Milvus
Il s'agit de la stratégie par défaut de Milvus. Cette stratégie tire parti de la technique de hachage pour attribuer à chaque canal une position sur l'anneau, puis effectue une recherche dans le sens des aiguilles d'une montre pour trouver le nœud de données le plus proche d'un canal. Ainsi, dans l'illustration ci-dessus, le canal 1 est attribué au nœud de données 2, tandis que le canal 2 est attribué au nœud de données 3.
Cette stratégie pose toutefois un problème : l'augmentation ou la diminution du nombre de nœuds de données (par exemple, le démarrage d'un nouveau nœud de données ou la fermeture soudaine d'un nœud de données) peut affecter le processus d'attribution des canaux. Pour résoudre ce problème, la coordination des données surveille l'état des nœuds de données via etcd afin que la coordination des données puisse être immédiatement informée de tout changement dans l'état des nœuds de données. La coordination des données détermine ensuite à quel nœud de données allouer correctement les canaux.
- Équilibrage de la charge
La deuxième stratégie consiste à attribuer des canaux de la même collection à différents nœuds de données, en veillant à ce que les canaux soient attribués de manière égale. L'objectif de cette stratégie est d'équilibrer la charge.
Attribution des données : quand et comment
Le processus d'attribution des données dans Milvus
Le processus d'attribution des données commence par le client. Il envoie d'abord des demandes d'insertion de données avec un horodatage t1
au mandataire. Ensuite, le proxy envoie une demande d'allocation de segments à la coordination des données.
Dès réception de la demande d'allocation de segments, la coordination des données vérifie l'état des segments et les alloue. Si l'espace actuel des segments créés est suffisant pour les lignes de données nouvellement insérées, la coordination des données alloue ces segments créés. Toutefois, si l'espace disponible dans les segments actuels n'est pas suffisant, la coordonnée des données alloue un nouveau segment. La coordonnée des données peut renvoyer un ou plusieurs segments à chaque demande. Entre-temps, la coordonnée des données enregistre également le segment alloué dans le méta-serveur pour la persistance des données.
Ensuite, la coordonnée des données renvoie au mandataire les informations relatives au segment alloué (notamment l'identifiant du segment, le nombre de lignes, le délai d'expiration t2
, etc. Le proxy envoie ces informations sur le segment alloué au magasin de messages afin qu'elles soient correctement enregistrées. Notez que la valeur de t1
doit être inférieure à celle de t2
. La valeur par défaut de t2
est de 2 000 millisecondes et peut être modifiée en configurant le paramètre segment.assignmentExpiration
dans le fichier data_coord.yaml
.
Structure du fichier Binlog et persistance des données
Rinçage du nœud de données
Le nœud de données s'abonne au magasin de messages parce que les demandes d'insertion de données sont conservées dans le magasin de messages et que les nœuds de données peuvent ainsi consommer les messages d'insertion. Les nœuds de données placent d'abord les demandes d'insertion dans un tampon d'insertion et, au fur et à mesure que les demandes s'accumulent, elles sont évacuées vers le stockage d'objets après avoir atteint un certain seuil.
Structure du fichier Binlog
Structure du fichier binlog.
La structure du fichier binlog dans Milvus est similaire à celle de MySQL. Le fichier binlog est utilisé pour remplir deux fonctions : la récupération des données et la construction d'un index.
Un journal contient de nombreux événements. Chaque événement comporte un en-tête et des données.
Les métadonnées, notamment l'heure de création du binlog, l'ID du nœud d'écriture, la longueur de l'événement et NextPosition (décalage de l'événement suivant), etc. sont écrites dans l'en-tête de l'événement.
Les données de l'événement peuvent être divisées en deux parties : fixes et variables.
Structure de fichier d'un événement d'insertion.
La partie fixe des données d'événement d'un INSERT_EVENT
contient StartTimestamp
, EndTimestamp
et reserved
.
La partie variable stocke en fait les données insérées. Les données d'insertion sont séquencées au format parquet et stockées dans ce fichier.
Persistance des données
S'il y a plusieurs colonnes dans le schéma, Milvus stocke les binlogs dans les colonnes.
Persistance des données du journal binôme.
Comme illustré dans l'image ci-dessus, la première colonne est la clé primaire binlog. La deuxième est la colonne d'horodatage. Les autres colonnes sont celles définies dans le schéma. Le chemin d'accès aux fichiers binlogs dans MinIO est également indiqué dans l'image ci-dessus.
À propos de la série Deep Dive
Avec l'annonce officielle de la disponibilité générale de Milvus 2.0, nous avons orchestré cette série de blogs Milvus Deep Dive afin de fournir une interprétation approfondie de l'architecture et du code source de Milvus. Les sujets abordés dans cette série de blogs sont les suivants
- Récapitulatif de l'architecture Milvus
- Le portail des demandes d'insertion de données
- Coordonnée des données et nœud de données
- Root coord et Time Tick
- Organisation des données : collection, partition, shard (canal), segment
- Attribution des données : quand et comment
- Structure du fichier Binlog et persistance des données
- À propos de la série Deep Dive
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