Compréhension approfondie du stockage de réplication de la série Kafka (quatre) -Kafka et du processus de traitement des demandes

Répertoire d'articles de la série

Articles de la série de guides faisant autorité Kakfa

Préface

Cette série est ma transcription et mes réflexions après avoir lu le livre "Le guide définitif de Kafka".

texte

Appartenance au cluster

Kafka utilise zookeeper pour maintenir la relation entre les membres du cluster. Chaque courtier a un identifiant unique (c'est-à-dire clientId, qui peut également être généré automatiquement).

  1. Lors du démarrage d'un courtier, le courtier enregistre son ID en créant un nœud temporaire sur zookeeper. Le chemin est: / brokers / ids. Par conséquent, lorsque le courtier rejoint ou quitte le cluster, ces membres recevront des notifications pertinentes.
  2. Si vous avez démarré un courtier avec l'ID A, vous devez également démarrer un courtier avec l'ID A. Ensuite, le courtier recevra une erreur. ( Deux courtiers avec le même identifiant ne peuvent pas exister en même temps )
  3. Si le courtier susmentionné avec l'ID A est complètement arrêté, puis qu'un nouveau courtier (ID également A) est démarré, le nouveau courtier rejoindra immédiatement le cluster et aura la même partition et le même sujet que l'ancien courtier.

Manette

Le contrôleur est essentiellement un courtier, mais comparé aux autres courtiers ordinaires, il a également la fonction d'élection du chef de partition.

Quelle est la norme produite par le contrôleur?

Le premier démarrage sera un périphérique de contrôle kafka courtier réussi , il créera un nœud / contrôleur temporaire sur le gardien de zoo.

Lorsque les derniers courtiers seront démarrés, ils essaieront également de créer des nœuds / contrôleurs temporaires sur zookeeper, mais ils recevront une exception "nœud existe déjà", puis se rendront compte qu'il y a déjà un contrôleur dans le cluster, puis ils Zookeeper Watch des objets seront créés sur le nœud de contrôleur afin qu'ils puissent être informés des modifications apportées à ce nœud.

Si le contrôleur et le gardien de zoo sont déconnectés, que se passera-t-il ensuite?

1. Ensuite, le nœud temporaire sur le gardien de zoo disparaîtra.
2. Ensuite, les autres courtiers du cluster seront informés de la disparition du nœud contrôleur via l'objet de surveillance. Ils essaieront de se faire le nouveau contrôleur.
3. Suivez ensuite les normes ci-dessus, le premier courtier qui crée avec succès un nœud temporaire sur le gardien de zoo deviendra le nouveau contrôleur. Une fois le nœud temporaire créé avec succès, les autres courtiers qui tentent de devenir un nouveau contrôleur recevront les exceptions correspondantes.

Y aura-t-il deux contrôleurs? Si oui, que dois-je faire?

Le premier est oui.
Exemple: Supposons que le contrôleur d'origine soit considéré comme étant en panne en raison de la congestion du réseau, et une fois que le nœud temporaire disparaît, les autres courtiers ne commenceront pas à se concurrencer pour devenir le contrôleur. Lorsqu'un nouveau contrôleur est créé, l'ancien réseau de contrôleurs revient à la normale. Ensuite, il y a un problème typique:
un problème de cerveau partagé

Comment Kafka résout-il le problème du cerveau divisé?

1. Revenez aux étapes précédentes Si un contrôleur raccroche et que d'autres courtiers élisent un nouveau contrôleur, ils doivent créer un nouvel objet de surveillance sur le nouveau contrôleur.

2. Ensuite, le nouveau contrôleur obtiendra une toute nouvelle époque de contrôleur avec une valeur plus grande grâce à l'opération d'incrémentation conditionnelle de zookeeper , qui peut être comprise comme la clé primaire de la base de données.

3. Ensuite, si d'autres courtiers reçoivent par la suite un message contenant l'ancienne époque du contrôleur après avoir connu la dernière époque actuelle du contrôleur, ils seront ignorés.


Réplication Kafka

La fonction de réplication de Kafka peut être considérée comme un noyau de l'architecture Kafka.
Voici un bref résumé de la structure organisationnelle de Kafka.

  1. Utilisez des rubriques pour organiser les données.
  2. Chaque sujet est divisé en plusieurs partitions. (La partition peut être comprise comme partager la quantité de données et la stocker séparément)
  3. Il existe plusieurs copies de chaque partition. (La copie peut être comprise comme la copie de données, utilisée pour une fiabilité élevée)
  4. La copie est enregistrée sur le courtier.

Type de copie:

  1. Copie du patron

1. Comme mentionné ci-dessus, chaque partition peut avoir plusieurs copies.
2. Mais une seule copie est la copie du boss.
3. Toutes les demandes des producteurs et des consommateurs passent par la copie principale.

  1. Copie d'abonné

1. Toutes les copies autres que la copie principale sont des copies suiveuses.
2. La copie suiveuse ne traite aucune demande.
3. Leur seul rôle est de copier les messages de la copie principale pour maintenir la cohérence. Et lorsque la copie de boss s'effondre, élisez une nouvelle copie de boss.


Voici une explication de la raison pour laquelle la copie suiveuse ne traite aucune demande.

1. Supposons qu'un utilisateur fasse la même demande de consommation deux fois de suite. Il existe deux copies suiveuses, une A et une B, et A s'est synchronisée avec la copie principale, mais pas B.
2. Pour la première fois lu à partir de la copie suiveuse A, le message lu est bonjour.
3. La deuxième lecture de la copie B du suiveur, le message lu est bonjour le monde.
4. Ensuite, le problème vient, les données lues la deuxième fois sont des données sales et les données réelles sont A, ce qui entraîne une incohérence des données. Par conséquent, Kafka autorise directement et simplement toutes les demandes des consommateurs à passer par le réplica principal.


Puis le problème se reproduit : si une copie maître échoue et que les autres copies esclaves sont sélectionnées, comment s'assurer que les données enregistrées dans la copie choisie doivent être complètes?

Avant de répondre à cette question, permettez-moi de parler de deux concepts, les copies synchrones ou non synchronisées.

  1. Copie désynchronisée

1. Tout d'abord, la prémisse suivante, afin de maintenir la synchronisation avec la copie leader, les abonnés doivent envoyer une demande de données à la copie leader. (Cela peut être considéré comme une demande du consommateur).
2. Le leader envoie le message de réponse au suiveur, et ces messages de demande contiennent le décalage que le suiveur souhaite obtenir le message, et le décalage est dans l'ordre.
3. Si le suiveur n'a demandé aucun message dans les 10 secondes ou n'a pas demandé les dernières données dans les 10 secondes, cette copie est considérée comme désynchronisée.
Remarque: ce 10s peut être spécifié en configurant le paramètre replica.lag.time.max.ms

  1. Copie de synchronisation

Les nouvelles obtenues par la demande continue sont toujours les plus récentes, une telle copie est appelée copie synchronisée.

Puis revenons à la question précédente: comment s'assurer que les données sont complètes?

Dans Kafka, lorsque le leader échoue, seule la copie synchronisée peut être sélectionnée comme nouveau leader.


Traitement de la demande

  1. Chaque courtier exécutera un thread Acceptor sur chaque port qu'il surveille. Ce thread créera une connexion et transmettra la connexion au thread Processor pour traitement.
  2. Le thread du processeur est chargé d'obtenir les messages de demande du client, de les placer dans la file d'attente des demandes, puis d'obtenir les messages de réponse de la file d'attente de réponses et de les envoyer au client.

Le processus général est le suivant:
Insérez la description de l'image ici
Il existe deux types courants de threads IO dans la figure: (les threads IO sont responsables du traitement des messages de file d'attente)

  1. Demande de production: La demande envoyée par le producteur, y compris le message que le client souhaite écrire au courtier.
  2. Obtenir la demande: la demande envoyée lorsque les copies du consommateur et de l'abonné doivent lire le message du courtier.

Ici, nous devons noter que les deux requêtes ci-dessus doivent être envoyées à la copie principale de la partition.

Question 1: Que faire si un courtier reçoit une demande pour une partition spécifique, mais que le chef de la partition est sur un autre courtier ?

Réponse: Ensuite, le client qui a envoyé la demande recevra une réponse d'erreur "non-chef de partition".

Par conséquent, le client Kafka doit être responsable de l'envoi de la demande au courtier approprié.

Question 2: Comment le client sait-il où envoyer la demande?

Réponse: Le client utilise le type de demande de la demande de métadonnées .
Le contenu de la requête comprend une liste de rubriques qui intéressent le client. En règle générale, le message de réponse côté serveur spécifie les partitions incluses dans la rubrique, la distribution des partitions, quelle copie est le chef de file, etc.
En outre, les demandes de métadonnées peuvent être envoyées à n'importe quel courtier, car tous les courtiers ont mis ces informations en cache.


Demande de production

En regardant le contenu précédent, le producteur a une configuration de paramètres appelée acks

  1. acks = 1: Tant que le leader reçoit le message, le message est considéré comme écrit avec succès.
  2. acks = all: tous les réplicas synchronisés doivent recevoir le message pour être considérés comme réussis.
  3. acks = 0: une fois que le producteur a envoyé un message, il n'est pas nécessaire d'attendre que le courtier réponde.

Ensuite, lorsque le courtier contenant une copie du leader reçoit une demande de production, il entreprendra les étapes suivantes pour la demande:

  1. Vérification des autorisations: l'utilisateur qui envoie les données a-t-il l'autorisation d'écrire le sujet?
  2. Vérification des paramètres: la valeur des acks est-elle valide? (Seulement 0, 1, tous)
  3. Vérification de réplique: si acks = all, existe-t-il suffisamment de répliques synchronisées pour garantir que le message a été écrit en toute sécurité? (Si le nombre est insuffisant, Kafka peut refuser d'écrire)
  4. Écriture de message: écriture sur le disque local.
  5. Vérifier les paramètres: une fois le message écrit sur le chef de partition , vérifiez le paramètre acks. Si acks = 0 ou 1, le courtier renvoie une réponse immédiatement. Si acks = all, enregistrez la demande dans un tampon du purgatoire , jusqu'à ce que le leader trouve que toutes les copies suiveuses ont copié le message, la réponse sera renvoyée au client.

Obtenir la demande

La manière dont le courtier traite les requêtes de récupération est très similaire à la manière de produire des requêtes. En une phrase: le client envoie une demande au courtier pour un message avec un décalage spécifique dans la partition de rubrique.

Mettez l'image en premier: les
Insérez la description de l'image ici
étapes générales sont:

  1. La demande est envoyée au chef de partition désigné, puis le client interroge les métadonnées pour s'assurer que l'itinéraire demandé est correct.
  2. Vérifiez si la requête est valide: si l'offset existe sur la partition, etc.
  3. Si le décalage demandé existe, le courtier lit le message à partir de la partition en fonction de la limite supérieure du nombre spécifié par le client, puis le renvoie au client.

Il y a plusieurs points à noter ici:
1. Kafka utilise la technologie zéro copie pour envoyer des messages au client: c'est-à-dire que le message est envoyé directement du fichier vers le canal réseau sans passer par des tampons intermédiaires.
2. Le client Kafka définit généralement les limites supérieure et inférieure des données renvoyées par le courtier pour contrôler la quantité de données renvoyées par le courtier à un moment donné.
3. Autrement dit, si la quantité de données n'atteint pas la limite inférieure, après l'envoi de la demande du courtier, le message ne sera pas reçu tant que la quantité de données ne sera pas suffisante.
4. Bien entendu, le client n'attendra pas que le courtier accumule des données pendant un certain temps. Si le volume de données ne répond toujours pas à la norme, les données seront renvoyées.

  1. Les données renvoyées sont des données synchrones.

Insérez la description de l'image ici


Stockage physique

L'unité de stockage de base de Kafka est une partition. Lorsque Kafka est configuré, une adresse de répertoire pour la partition de stockage est généralement spécifiée, qui est le paramètre log.dirs (server.properties, veillez à ne pas la confondre avec log.properties)

Ensuite, nous verrons comment Kafka effectue l'allocation de partition et le stockage des données.

Allocation de partition

Lorsque Kafka crée un sujet, il décide comment allouer des partitions entre les courtiers.

Exemple: nous avons 6 courtiers, nous prévoyons de créer un sujet avec 10 partitions, et le facteur de réplication est de 3 (la quantité de copie), puis il y aura un total de 10 * 3 = 30 copies de partition, qui seront allouées à 6 courtiers. Lors de l'allocation de partition, Kafka doit exiger les éléments suivants:

  1. Les copies de partition sont uniformément réparties sur les courtiers. (Équivaut à une moyenne de 5 copies de partition pour chaque courtier)
  2. Assurez-vous que différentes copies de chaque partition sont distribuées sur différents courtiers. (Chaque partition a 3 copies, y compris une copie principale et une copie suiveuse), ce qui signifie que les copies maître et esclave doivent être allouées sur différents courtiers, et plusieurs copies de la même partition ne peuvent pas être sur le même courtier. Reportez-vous à l'image ci-dessous

Insérez la description de l'image ici

Gestion et indexation des fichiers

Il existe deux façons de gérer les fichiers dans Kafka: la durée de stockage et la taille de stockage. Pour plus de détails, consultez les paramètres de l'article producteur.

Généralement, Kafka divise la partition en plusieurs fragments. ** Par défaut, chaque fragment contient 1 Go ou une semaine de données, et le plus petit prévaudra. ** Lorsque le courtier écrit des données sur la partition, si la limite de fragments est atteinte, le fichier actuel est fermé et un nouveau fichier est ouvert.

Le segment qui écrit actuellement des données est appelé le segment actif et le segment actif ne sera jamais supprimé.

Alors, quel est le format du fichier écrit?

Nous savons que Kafka enregistre le message et le décalage dans un fichier, alors que contient le fichier?
Insérez la description de l'image ici
Outre les paires clé-valeur et les décalages, le message contient également la taille, la somme de contrôle, le numéro de version du format du message, l'algorithme de compression (Snappy, Gzip, Lz4) et l'horodatage du message. L'horodatage fait référence à l'heure à laquelle le message arrive chez le courtier. Mais vous pouvez remarquer que le coin inférieur droit de l'image ci-dessus est noir, ce qui signifie que le producteur envoie un message compressé. , Ensuite, le même lot de messages sera compressé ensemble et envoyé sous forme de messages empaquetés.

Utilisez un outil fourni avec Kafka pour voir le contenu du fragment (contenu du message)

./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --deep-iteration 文件

Les consommateurs peuvent commencer à lire les messages à partir de n'importe quel offset disponible dans Kafka, alors comment les consommateurs le localisent-ils?

Réponse: utilisez l'index.
Kafka gère un index pour chaque partition. L'index mappe l'offset sur le fichier fragment et la position de l'offset dans le fichier. Bien entendu, l'index sera également divisé en fragments, donc lors de la suppression d'un message, l'index correspondant sera également supprimé.

Nettoyage des fichiers et principe de fonctionnement

Chaque fragment de journal de Kafka peut être divisé en deux parties.

  1. Nettoyer la partie: ces messages ont déjà été nettoyés et chaque clé n'a qu'une seule valeur correspondante, qui est conservée lors du dernier nettoyage.
  2. La partie sale: Ces messages sont des données écrites après le dernier nettoyage.
    Comme montré:
    Insérez la description de l'image ici

Kafka peut configurer sa propre fonction de nettoyage (log.cleaner.enabled). S'il est démarré, chaque courtier démarrera un thread de gestionnaire de nettoyage et plusieurs threads de nettoyage. Les threads de nettoyage sont responsables de l'exécution des tâches de nettoyage. Ils sélectionneront le taux de pollution (sale message La partition avec la proportion la plus élevée de la taille totale de la partition) est nettoyée.

Le thread de nettoyage créera une carte en mémoire. Chaque élément de cette carte contient la valeur de hachage et l'offset de la clé de message. La valeur de hachage de la clé est 16B et l'offset est de 24B au total. Donc, si vous voulez nettoyer un fragment de journal de 1 Go, en supposant que la taille de chaque message est de 1 Ko, alors ce fragment contient un million de messages, et nous n'avons besoin que d'une carte de 24 Mo pour nettoyer ce fragment, ce qui est très efficace.

Principe de fonctionnement approximatif :

  1. Une fois que le thread de nettoyage a créé la carte de décalage, il commence à lire le message à partir du fragment le plus propre, qui est le message le plus ancien, et compare leur contenu avec le contenu de la carte.
  2. Vérifiez si la clé du message existe dans le mappage. Si elle n'existe pas, cela signifie que la valeur du message est la plus récente et le message sera copié dans le fragment remplacé. S'il existe, le message sera ignoré.
  3. Après avoir copié tous les messages, nous échangeons le fragment de remplacement avec le fragment d'origine , puis commençons à nettoyer le fragment suivant.
  4. Après avoir terminé tout le processus de nettoyage, chaque clé correspond à un message différent (la valeur du message est la dernière), l'image est la suivante:

Insérez la description de l'image ici


Ce qui précède peut être résumé de manière modeste, nous ne conserverons qu'un seul message récent pour chaque clé.

Question 1: Mais que dois-je faire si je dois supprimer tous les messages correspondant à une certaine clé. (Par exemple, un utilisateur n'utilise plus un certain service et doit supprimer tous les messages du client)

Réponse:
1. Pour supprimer complètement une clé du système, l'application doit envoyer un message contenant la clé avec une valeur nulle.
2. Lorsque le thread de nettoyage trouve le message, il effectue d'abord un nettoyage régulier et ne conserve que le message dont la valeur est null. Le message avec une valeur nulle, nous l'appelons un message tombstone , sera conservé pendant un certain temps.
3. Pendant cette période, le consommateur peut voir le message de désactivation, mais constate que sa valeur a été supprimée.
4. Après cette période, le thread de nettoyage supprimera le message de désactivation et la clé correspondante sera également supprimée de la partition Kafka.

Question 2: Pourquoi le message de la pierre tombale est-il conservé pendant une courte période de temps?

Réponse: 1. Tout d'abord, le temps de rétention peut être configuré.
2. Deuxièmement, le temps de rétention est configuré pour permettre aux consommateurs de voir le message de désactivation pendant cette période, afin que les consommateurs comprennent que la valeur de ce message a été supprimée et que les consommateurs professionnels comprennent: Oh, ce message n'est plus utile maintenant , tous les messages pertinents doivent être supprimés de la base de données.


Pour résumer

Cet article décrit les aspects suivants:

  1. Appartenance au cluster et contrôleur.
  2. Processus de réplication et de traitement des demandes de Kafka.
  3. Stockage et format de fichier de Kafka, principe de compensation.

Le prochain article va parler de la transmission de données fiable de Kafka.

Je suppose que tu aimes

Origine blog.csdn.net/Zong_0915/article/details/109578284
conseillé
Classement