« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Je vous suggère de lire la transcription de la conférence "Hadoop. ZooKeeper" de la série "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Qu'est-ce que ZooKeeper, sa place dans l'écosystème Hadoop. Des contrevérités sur l'informatique distribuée. Schéma d'un système distribué standard. Difficulté à coordonner les systèmes distribués. Problèmes de coordination typiques. Les principes derrière la conception de ZooKeeper. Modèle de données ZooKeeper. drapeaux de nœud z. Séances. API cliente. Primitives (configuration, appartenance à un groupe, verrouillages simples, élection du leader, verrouillage sans effet troupeau). Architecture ZooKeeper. Base de données ZooKeeper. ZAB. Gestionnaire de requêtes.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Aujourd'hui, nous allons parler de ZooKeeper. Cette chose est très utile. Comme tout produit Apache Hadoop, il possède un logo. Il représente un homme.

Avant cela, nous avons principalement parlé de la manière dont les données peuvent y être traitées, comment les stocker, c'est-à-dire comment les utiliser d'une manière ou d'une autre et travailler avec elles d'une manière ou d'une autre. Et aujourd'hui, j'aimerais parler un peu de la création d'applications distribuées. Et ZooKeeper est une de ces choses qui vous permet de simplifier cette affaire. Il s'agit d'une sorte de service destiné à une sorte de coordination de l'interaction des processus dans des systèmes distribués, dans des applications distribuées.

Le besoin de telles applications devient de plus en plus grand chaque jour, c'est l'objet de notre cours. D'une part, MapReduce et ce framework prêt à l'emploi permettent de niveler cette complexité et de libérer le programmeur de l'écriture de primitives telles que l'interaction et la coordination des processus. Mais d’un autre côté, personne ne garantit que cela ne sera pas nécessaire de toute façon. MapReduce ou d'autres frameworks prêts à l'emploi ne remplacent pas toujours complètement certains cas qui ne peuvent pas être implémentés à l'aide de celui-ci. Y compris MapReduce lui-même et un tas d'autres projets Apache ; ce sont en fait également des applications distribuées. Et pour faciliter l'écriture, ils ont écrit ZooKeeper.

Comme toutes les applications liées à Hadoop, elle a été développée par Yahoo! C'est désormais également une application Apache officielle. Il n'est pas aussi activement développé que HBase. Si vous allez sur JIRA HBase, il y a chaque jour un tas de rapports de bugs, un tas de propositions pour optimiser quelque chose, c'est-à-dire que la vie dans le projet continue constamment. Et ZooKeeper, d'une part, est un produit relativement simple, et d'autre part, cela garantit sa fiabilité. Et il est assez simple à utiliser, c’est pourquoi il est devenu un standard dans les applications de l’écosystème Hadoop. J’ai donc pensé qu’il serait utile de le revoir pour comprendre son fonctionnement et comment l’utiliser.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Ceci est une image d'une conférence que nous avons eue. On peut dire qu’elle est orthogonale à tout ce que nous avons considéré jusqu’à présent. Et tout ce qui est indiqué ici, à un degré ou à un autre, fonctionne avec ZooKeeper, c'est-à-dire qu'il s'agit d'un service qui utilise tous ces produits. Ni HDFS ni MapReduce n'écrivent leurs propres services similaires qui fonctionneraient spécifiquement pour eux. En conséquence, ZooKeeper est utilisé. Et cela simplifie le développement et certaines choses liées aux erreurs.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

D'où vient tout cela ? Il semblerait que nous ayons lancé deux applications en parallèle sur des ordinateurs différents, que nous les avons connectées avec une chaîne ou un maillage, et que tout fonctionne. Mais le problème est que le réseau n'est pas fiable, et si vous reniflez le trafic ou regardez ce qui s'y passe à un niveau bas, comment les clients interagissent sur le réseau, vous pouvez souvent constater que certains paquets sont perdus ou renvoyés. Ce n'est pas pour rien que les protocoles TCP ont été inventés, qui permettent d'établir une certaine session et de garantir la livraison des messages. Mais dans tous les cas, même TCP ne peut pas toujours vous sauver. Tout a un délai d'attente. Le réseau peut simplement s'effondrer pendant un certain temps. Il se peut qu'il clignote. Et tout cela conduit au fait que vous ne pouvez pas compter sur la fiabilité du réseau. C'est la principale différence avec l'écriture d'applications parallèles qui s'exécutent sur un ordinateur ou sur un superordinateur, où il n'y a pas de réseau, où il existe un bus d'échange de données plus fiable en mémoire. Et c'est une différence fondamentale.

Entre autres choses, lors de l’utilisation du Réseau, il y a toujours une certaine latence. Le disque en possède également, mais le Réseau en possède davantage. La latence est un certain temps de retard, qui peut être faible ou assez important.

La topologie du réseau évolue. Qu'est-ce que la topologie - c'est l'emplacement de nos équipements réseau. Il y a des centres de données, il y a des racks qui sont là, il y a des bougies. Tout cela peut être reconnecté, déplacé, etc. Tout cela doit également être pris en compte. Les noms IP changent, l’itinéraire par lequel circule notre trafic change. Cela doit également être pris en compte.

Le réseau peut également évoluer en termes d'équipements. D'après la pratique, je peux dire que nos ingénieurs réseau aiment vraiment mettre à jour périodiquement quelque chose sur les bougies. Soudain, un nouveau firmware est sorti et ils n'étaient pas particulièrement intéressés par certains clusters Hadoop. Ils ont leur propre travail. Pour eux, l’essentiel est que le Réseau fonctionne. En conséquence, ils souhaitent y télécharger à nouveau quelque chose, effectuer un flashage sur leur matériel, et le matériel change également périodiquement. Tout cela doit, d’une manière ou d’une autre, être pris en compte. Tout cela affecte notre application distribuée.

Habituellement, les personnes qui commencent à travailler avec de grandes quantités de données pour une raison quelconque pensent qu'Internet est illimité. S'il y a un fichier de plusieurs téraoctets, vous pouvez le transférer sur votre serveur ou votre ordinateur et l'ouvrir en utilisant cat et regarde. Une autre erreur est dans Vim regardez les journaux. Ne faites jamais ça parce que c'est mauvais. Parce que Vim essaie de tout mettre en mémoire tampon, de tout charger en mémoire, surtout lorsque nous commençons à parcourir ce journal et à chercher quelque chose. Ce sont des choses oubliées, mais qui méritent d’être prises en compte.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Il est plus facile d'écrire un programme qui s'exécute sur un ordinateur avec un seul processeur.

Lorsque notre système grandit, nous souhaitons tout paralléliser, et le paralléliser non seulement sur un ordinateur, mais également sur un cluster. La question se pose : comment coordonner ce dossier ? Nos applications n'interagissent peut-être même pas entre elles, mais nous avons exécuté plusieurs processus en parallèle sur plusieurs serveurs. Et comment contrôler que tout va bien pour eux ? Par exemple, ils envoient quelque chose sur Internet. Ils doivent écrire sur leur état quelque part, par exemple dans une sorte de base de données ou de journal, puis regrouper ce journal et l'analyser quelque part. De plus, nous devons tenir compte du fait que le processus fonctionnait et fonctionnait, qu'une erreur y est soudainement apparue ou qu'il s'est écrasé, alors à quelle vitesse le saurons-nous ?

Il est clair que tout cela peut être surveillé rapidement. C'est également une bonne chose, mais la surveillance est une chose limitée qui vous permet de surveiller certaines choses au plus haut niveau.

Lorsque nous voulons que nos processus commencent à interagir les uns avec les autres, par exemple pour s'envoyer des données, la question se pose également : comment cela se produira-t-il ? Y aura-t-il une sorte de condition de concurrence, vont-ils s’écraser les uns les autres, les données arriveront-elles correctement, est-ce que quelque chose sera perdu en cours de route ? Nous devons développer une sorte de protocole, etc.

La coordination de tous ces processus n’est pas une mince affaire. Et cela oblige le développeur à descendre à un niveau encore plus bas et à écrire des systèmes soit à partir de zéro, soit pas tout à fait à partir de zéro, mais ce n'est pas si simple.

Si vous proposez un algorithme cryptographique ou même si vous l'implémentez, jetez-le immédiatement, car il ne fonctionnera probablement pas pour vous. Il contiendra très probablement un certain nombre d'erreurs que vous avez oublié de prévoir. Ne l'utilisez jamais pour quelque chose de grave car il sera probablement instable. Car tous les algorithmes qui existent ont été éprouvés par le temps depuis très longtemps. Il est buggé par la communauté. Il s'agit d'un sujet distinct. Et c'est pareil ici. S'il est possible de ne pas mettre en œuvre vous-même une sorte de synchronisation des processus, il est préférable de ne pas le faire, car cela est assez compliqué et vous conduit sur le chemin fragile de la recherche constante d'erreurs.

Aujourd'hui, nous parlons de ZooKeeper. D'une part, c'est un framework, d'autre part, c'est un service qui facilite la vie du développeur et simplifie au maximum la mise en œuvre de la logique et la coordination de nos processus.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Rappelons-nous à quoi pourrait ressembler un système distribué standard. C'est ce dont nous avons parlé - HDFS, HBase. Il existe un processus maître qui gère les processus travailleurs et esclaves. Il est responsable de la coordination et de la répartition des tâches, du redémarrage des travailleurs, du lancement de nouveaux et de la répartition de la charge.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Une chose plus avancée est le service de coordination, c'est-à-dire déplacer la tâche de coordination elle-même dans un processus séparé, et exécuter en parallèle une sorte de maître de sauvegarde ou de secours, car le maître peut échouer. Et si le Maître tombe, alors notre système ne fonctionnera pas. Nous effectuons une sauvegarde. Certains indiquent que le maître doit être répliqué en sauvegarde. Cela peut également être confié au Service de Coordination. Mais dans ce diagramme, le Maître lui-même est responsable de la coordination des travailleurs ; ici, le service coordonne les activités de réplication des données.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Une option plus avancée est celle où toute la coordination est gérée par notre service, comme cela se fait habituellement. Il prend la responsabilité de s'assurer que tout fonctionne. Et si quelque chose ne fonctionne pas, nous le découvrons et essayons de contourner cette situation. Dans tous les cas, nous nous retrouvons avec un maître qui interagit d'une manière ou d'une autre avec les esclaves et peut envoyer des données, des informations, des messages, etc. via un service.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Il existe un schéma encore plus avancé, lorsque l'on n'a pas de maître, tous les nœuds sont des maîtres esclaves, différents dans leur comportement. Mais ils doivent encore interagir les uns avec les autres, il reste donc encore du service pour coordonner ces actions. Cassandra, qui travaille selon ce principe, correspond probablement à ce schéma.

Il est difficile de dire lequel de ces systèmes fonctionne le mieux. Chacun a ses propres avantages et inconvénients.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Et il n'est pas nécessaire d'avoir peur de certaines choses avec le Maître, car, comme le montre la pratique, il n'est pas si enclin à servir constamment. L'essentiel ici est de choisir la bonne solution pour héberger ce service sur un nœud puissant distinct, afin qu'il dispose de suffisamment de ressources, afin que, si possible, les utilisateurs n'y aient pas accès, afin qu'ils ne tuent pas accidentellement ce processus. Mais en même temps, dans un tel schéma, il est beaucoup plus facile de gérer les travailleurs du processus Master, c'est-à-dire que ce schéma est plus simple du point de vue de la mise en œuvre.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Et ce schéma (ci-dessus) est probablement plus complexe, mais plus fiable.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Le principal problème réside dans les échecs partiels. Par exemple, lorsque nous envoyons un message sur le réseau, une sorte d'accident se produit, et celui qui a envoyé le message ne saura pas si son message a été reçu et ce qui s'est passé du côté du destinataire, ne saura pas si le message a été traité correctement. , c'est-à-dire qu'il ne recevra aucune confirmation.

En conséquence, nous devons traiter cette situation. Et le plus simple est de renvoyer ce message et d'attendre que nous recevions une réponse. Dans ce cas, il n'est pas pris en compte si l'état du récepteur a changé. Nous pouvons envoyer un message et ajouter les mêmes données deux fois.

ZooKeeper propose des moyens de gérer de tels refus, ce qui nous facilite également la vie.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Comme mentionné un peu plus tôt, cela ressemble à l'écriture de programmes multithread, mais la principale différence est que dans les applications distribuées que nous construisons sur différentes machines, le seul moyen de communiquer est le réseau. Il s’agit essentiellement d’une architecture sans partage. Chaque processus ou service qui s'exécute sur une machine possède sa propre mémoire, son propre disque, son propre processeur, qu'il ne partage avec personne.

Si nous écrivons un programme multithread sur un ordinateur, nous pouvons alors utiliser la mémoire partagée pour échanger des données. Nous avons là un changement de contexte, les processus peuvent changer. Cela affecte les performances. D'une part, il n'y a rien de tel dans le programme sur un cluster, mais il y a des problèmes avec le réseau.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

En conséquence, les principaux problèmes qui surviennent lors de l’écriture de systèmes distribués sont la configuration. Nous écrivons une sorte d'application. Si c'est simple, alors nous codons en dur toutes sortes de nombres dans le code, mais cela n'est pas pratique, car si nous décidons qu'au lieu d'un délai d'attente d'une demi-seconde, nous voulons un délai d'attente d'une seconde, alors nous devons recompiler l'application et déroulez tout à nouveau. C'est une chose lorsqu'il est sur une seule machine, qu'il suffit de le redémarrer, mais lorsque nous avons plusieurs machines, nous devons constamment tout copier. Il faut essayer de rendre l'application configurable.

Nous parlons ici de configuration statique pour les processus système. Ce n'est pas entièrement, peut-être du point de vue du système d'exploitation, il peut s'agir d'une configuration statique pour nos processus, c'est-à-dire qu'il s'agit d'une configuration qui ne peut pas simplement être prise et mise à jour.

Il existe également une configuration dynamique. Ce sont ces paramètres que nous souhaitons modifier à la volée pour qu'ils soient captés là-bas.

Quel est le problème ici ? Nous avons mis à jour la configuration, l'avons déployée, et alors ? Le problème est peut-être que d'une part nous avons déployé la configuration, mais avons oublié la nouveauté, la configuration est restée là. Deuxièmement, pendant le déploiement, la configuration a été mise à jour à certains endroits, mais pas à d'autres. Et certains processus de notre application qui s'exécutent sur une machine ont été redémarrés avec une nouvelle configuration, et quelque part avec une ancienne. Cela peut entraîner une incohérence de notre application distribuée du point de vue de la configuration. Ce problème est courant. Pour une configuration dynamique, elle est plus pertinente car elle implique qu'elle puisse être modifiée à la volée.

Un autre problème est l’appartenance à un groupe. Nous avons toujours un groupe de travailleurs, nous voulons toujours savoir lequel d'entre eux est vivant, lequel est mort. S'il existe un maître, il doit alors comprendre quels travailleurs peuvent être redirigés vers les clients afin qu'ils effectuent des calculs ou travaillent avec des données, et lesquels ne le peuvent pas. Un problème qui se pose constamment est que nous devons savoir qui travaille dans notre cluster.

Un autre problème typique est celui des élections des dirigeants, lorsque nous voulons savoir qui est aux commandes. Un exemple est la réplication, lorsqu'un processus reçoit des opérations d'écriture et les réplique ensuite parmi d'autres processus. Il sera le leader, tous les autres lui obéiront, le suivront. Il est nécessaire de choisir un processus qui soit sans ambiguïté pour tout le monde, afin qu'il n'arrive pas que deux dirigeants soient sélectionnés.

Il existe également un accès mutuellement exclusif. Le problème ici est plus complexe. Il existe un mutex, lorsque vous écrivez des programmes multithread et souhaitez que l'accès à une ressource, par exemple une cellule mémoire, soit limité et effectué par un seul thread. Ici, la ressource pourrait être quelque chose de plus abstrait. Et différentes applications de différents nœuds de notre réseau ne devraient recevoir qu'un accès exclusif à une ressource donnée, et non pour que tout le monde puisse la modifier ou y écrire quelque chose. Ce sont ce qu'on appelle les serrures.

ZooKeeper vous permet de résoudre tous ces problèmes à un degré ou à un autre. Et je vais montrer avec des exemples comment cela vous permet de faire cela.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Il n’y a pas de primitives bloquantes. Lorsque nous commençons à utiliser quelque chose, cette primitive n’attendra aucun événement. Très probablement, cette chose fonctionnera de manière asynchrone, permettant ainsi aux processus de ne pas se bloquer pendant qu'ils attendent quelque chose. C'est une chose très utile.

Toutes les demandes des clients sont traitées dans l'ordre de la file d'attente générale.

Et les clients ont la possibilité de recevoir une notification sur les changements dans un certain état, sur les changements dans les données, avant que le client ne voie lui-même les données modifiées.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

ZooKeeper peut fonctionner selon deux modes. Le premier est autonome, sur un seul nœud. C'est pratique pour les tests. Il peut également fonctionner en mode cluster sur un nombre illimité de serveurs. Si nous avons un cluster de 100 machines, il n’est pas nécessaire qu’il fonctionne sur 100 machines. Il suffit de sélectionner plusieurs machines sur lesquelles vous pouvez exécuter ZooKeeper. Et il professe le principe de haute disponibilité. Sur chaque instance en cours d'exécution, ZooKeeper stocke une copie complète des données. Plus tard, je vous dirai comment il fait. Il ne fragmente pas les données et ne les partitionne pas. D'une part, c'est un inconvénient que nous ne pouvons pas stocker grand-chose, d'autre part, ce n'est pas nécessaire. Ce n’est pas pour cela qu’il est conçu, ce n’est pas une base de données.

Les données peuvent être mises en cache côté client. C’est un principe standard pour ne pas interrompre le service et ne pas le charger avec les mêmes requêtes. Un client intelligent le sait généralement et le met en cache.

Par exemple, quelque chose a changé ici. Il existe une sorte d'application. Un nouveau leader a été élu, chargé par exemple du traitement des opérations d'écriture. Et nous voulons répliquer les données. Une solution consiste à le mettre en boucle. Et nous remettons constamment en question notre service : est-ce que quelque chose a changé ? La deuxième option est plus optimale. Il s'agit d'un mécanisme de surveillance qui vous permet d'informer les clients que quelque chose a changé. Il s’agit d’une méthode moins coûteuse en termes de ressources et plus pratique pour les clients.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Le client est l'utilisateur qui utilise ZooKeeper.

Le serveur est le processus ZooKeeper lui-même.

Znode est l'élément clé de ZooKeeper. Tous les znodes sont stockés en mémoire par ZooKeeper et sont organisés sous forme d'un diagramme hiérarchique, sous forme d'arborescence.

Il existe deux types d'opérations. La première est la mise à jour/écriture, lorsqu'une opération modifie l'état de notre arborescence. L'arbre est commun.

Et il est possible que le client ne complète pas une requête et soit déconnecté, mais puisse établir une session à travers laquelle il interagit avec ZooKeeper.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Le modèle de données de ZooKeeper ressemble à un système de fichiers. Il y a une racine standard et puis on a parcouru comme si les répertoires qui partaient de la racine. Et puis le catalogue du premier niveau, deuxième niveau. Ce sont tous des znodes.

Chaque znode peut stocker des données, généralement peu volumineuses, par exemple 10 kilo-octets. Et chaque znode peut avoir un certain nombre d'enfants.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Les Znodes sont de plusieurs types. Ils peuvent être créés. Et lors de la création d'un znode, nous précisons le type auquel il doit appartenir.

Il existe deux types. Le premier est le drapeau éphémère. Znode vit dans une session. Par exemple, le client a établi une session. Et tant que cette session sera vivante, elle existera. Cela est nécessaire pour ne pas produire quelque chose d'inutile. Cela convient également aux moments où il est important pour nous de stocker des primitives de données au sein d'une session.

Le deuxième type est le drapeau séquentiel. Il incrémente le compteur sur le chemin du znode. Par exemple, nous avions un répertoire avec l'application 1_5. Et lorsque nous avons créé le premier nœud, il a reçu p_1, le second - p_2. Et lorsque nous appelons cette méthode à chaque fois, nous transmettons le chemin complet, en indiquant seulement une partie du chemin, et ce numéro est automatiquement incrémenté car nous indiquons le type de nœud - séquentiel.

Znode régulier. Elle vivra toujours et portera le nom qu'on lui dit.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Une autre chose utile est le drapeau de montre. Si nous l'installons, le client peut alors s'abonner à certains événements pour un nœud spécifique. Je vous montrerai plus tard avec un exemple comment cela se fait. ZooKeeper lui-même informe le client que les données sur le nœud ont changé. Cependant, les notifications ne garantissent pas l'arrivée de nouvelles données. Ils disent simplement que quelque chose a changé, vous devrez donc encore comparer les données plus tard avec des appels séparés.

Et comme je l'ai déjà dit, l'ordre des données est déterminé en kilo-octets. Il n'est pas nécessaire d'y stocker des données textuelles volumineuses, car ce n'est pas une base de données, c'est un serveur de coordination d'actions.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Je vais vous parler un peu des séances. Si nous avons plusieurs serveurs, nous pouvons alors passer de manière transparente d'un serveur à l'autre en utilisant l'identifiant de session. C'est assez pratique.

Chaque session a une sorte de délai d'attente. Une session est définie par le fait que le client envoie ou non quelque chose au serveur pendant cette session. S'il n'a rien transmis pendant le délai d'attente, la session est interrompue ou le client peut la fermer lui-même.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Elle n'a pas beaucoup de fonctionnalités, mais vous pouvez faire différentes choses avec cette API. Cet appel que nous avons vu créer crée un znode et prend trois paramètres. Il s'agit du chemin d'accès au znode, et il doit être spécifié intégralement à partir de la racine. Et ce sont aussi des données que nous souhaitons y transférer. Et le type de drapeau. Et après la création, il renvoie le chemin vers le znode.

Deuxièmement, vous pouvez le supprimer. L'astuce ici est que le deuxième paramètre, en plus du chemin d'accès au znode, peut spécifier la version. En conséquence, ce znode sera supprimé si sa version que nous avons transférée est équivalente à celle qui existe réellement.

Si nous ne voulons pas vérifier cette version, alors nous passons simplement l'argument "-1".

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Troisièmement, il vérifie l'existence d'un znode. Renvoie vrai si le nœud existe, faux sinon.

Et puis un drapeau de surveillance apparaît, ce qui vous permet de surveiller ce nœud.

Vous pouvez définir cet indicateur même sur un nœud inexistant et recevoir une notification lorsqu'il apparaît. Cela peut également être utile.

Quelques autres défis sont obtenirDonnées. Il est clair que nous pouvons recevoir des données via znode. Vous pouvez également utiliser la surveillance du drapeau. Dans ce cas, il ne s'installera pas s'il n'y a pas de nœud. Par conséquent, vous devez comprendre qu'il existe, puis recevoir des données.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Il y a aussi SetData. Ici, nous passons la version. Et si nous transmettons cela, les données sur le znode d'une certaine version seront mises à jour.

Vous pouvez également spécifier "-1" pour exclure cette vérification.

Une autre méthode utile est obtenir des enfants. Nous pouvons également obtenir une liste de tous les znodes qui lui appartiennent. Nous pouvons surveiller cela en définissant une surveillance par drapeau.

Et la méthode synchroniser permet d'envoyer toutes les modifications en même temps, garantissant ainsi qu'elles sont enregistrées et que toutes les données ont été complètement modifiées.

Si nous faisons des analogies avec la programmation habituelle, alors lorsque vous utilisez des méthodes telles que write, qui écrivent quelque chose sur le disque, et après qu'elles vous ont renvoyé une réponse, il n'y a aucune garantie que vous avez écrit les données sur le disque. Et même lorsque le système d'exploitation est sûr que tout a été écrit, il existe des mécanismes dans le disque lui-même par lesquels le processus passe par des couches de tampons, et seulement après cela, les données sont placées sur le disque.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Les appels asynchrones sont principalement utilisés. Cela permet au client de travailler en parallèle sur différentes demandes. Vous pouvez utiliser l'approche synchrone, mais elle est moins productive.

Les deux opérations dont nous avons parlé sont la mise à jour/écriture, qui modifient les données. Ce sont créer, setData, synchroniser, supprimer. Et read existe, getData, getChildren.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Maintenant, quelques exemples de la façon dont vous pouvez créer des primitives pour travailler dans un système distribué. Par exemple, lié à la configuration de quelque chose. Un nouvel ouvrier est apparu. Nous avons ajouté la machine et démarré le processus. Et il y a les trois questions suivantes. Comment interroge-t-il ZooKeeper pour la configuration ? Et si on veut changer la configuration, comment la changer ? Et après l’avoir changé, comment les travailleurs que nous avions l’ont-ils obtenu ?

ZooKeeper rend cela relativement simple. Par exemple, il y a notre arbre znode. Il y a ici un nœud pour notre application, nous y créons un nœud supplémentaire, qui contient les données de la configuration. Il peut s'agir ou non de paramètres distincts. Comme la taille est petite, la taille de la configuration est généralement petite également, il est donc tout à fait possible de la stocker ici.

Vous utilisez la méthode obtenirDonnées pour obtenir la configuration du travailleur à partir du nœud. Définir sur vrai. Si pour une raison quelconque ce nœud n'existe pas, nous en serons informés lorsqu'il apparaîtra ou lorsqu'il changera. Si nous voulons savoir que quelque chose a changé, nous le définissons sur vrai. Et si les données de ce nœud changent, nous le saurons.

SetData. Nous définissons les données, définissons "-1", c'est-à-dire que nous ne vérifions pas la version, nous supposons que nous avons toujours une configuration, nous n'avons pas besoin de stocker plusieurs configurations. Si vous avez besoin de stocker beaucoup, vous devrez ajouter un autre niveau. Ici, nous pensons qu’il n’y en a qu’un, donc nous mettons à jour uniquement le dernier, donc nous ne vérifions pas la version. À ce stade, tous les clients précédemment abonnés reçoivent une notification indiquant que quelque chose a changé dans ce nœud. Et après les avoir reçues, ils doivent également demander à nouveau les données. La notification signifie qu'ils ne reçoivent pas les données elles-mêmes, mais uniquement la notification des modifications. Après cela, ils doivent demander de nouvelles données.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

La deuxième option pour utiliser la primitive est appartenance à un groupe. Nous avons une application distribuée, il y a un groupe de travailleurs et nous voulons comprendre qu'ils sont tous en place. Par conséquent, ils doivent s’inscrire eux-mêmes pour indiquer qu’ils travaillent dans notre application. Et nous voulons aussi connaître, soit par le processus Master, soit ailleurs, tous les travailleurs actifs que nous avons actuellement.

Comment faisons-nous cela? Pour l'application, nous créons un nœud de travail et y ajoutons un sous-niveau à l'aide de la méthode create. J'ai une erreur sur la diapositive. Ici, vous avez besoin séquentiel précisez, alors tous les travailleurs seront créés un par un. Et l'application, demandant toutes les données sur les enfants de ce nœud, reçoit tous les travailleurs actifs existants.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

C'est une implémentation tellement terrible de la façon dont cela peut être fait en code Java. Commençons par la fin, avec la méthode principale. C'est notre classe, créons sa méthode. Comme premier argument, nous utilisons l'hôte, là où nous nous connectons, c'est-à-dire que nous le définissons comme argument. Et le deuxième argument est le nom du groupe.

Comment se fait la connexion ? Ceci est un exemple simple de l'API utilisée. Tout est relativement simple ici. Il existe une classe standard ZooKeeper. Nous lui transmettons des hôtes. Et définissez le délai d'attente, par exemple, sur 5 secondes. Et nous avons un membre appeléconnectedSignal. Essentiellement, nous créons un groupe le long du chemin transmis. Nous n’y écrivons pas de données, même si quelque chose aurait pu être écrit. Et le nœud ici est du type persistant. Il s’agit essentiellement d’un nœud régulier ordinaire qui existera tout le temps. C'est ici que la session est créée. Il s'agit de l'implémentation du client lui-même. Notre client enverra des messages périodiques indiquant que la session est active. Et quand on termine la séance, on annonce la clôture et c'est tout, la séance s'arrête. C'est au cas où quelque chose tomberait pour nous, afin que ZooKeeper le découvre et interrompe la session.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Comment verrouiller une ressource ? Ici, tout est un peu plus compliqué. Nous avons un ensemble de travailleurs, il y a une ressource que nous voulons verrouiller. Pour ce faire, nous créons un nœud distinct, par exemple appelé lock1. Si nous parvenons à le créer, nous aurons un verrou ici. Et si nous n'avons pas pu le créer, alors le travailleur essaie d'obtenir getData à partir d'ici, et puisque le nœud a déjà été créé, alors nous mettons un observateur ici et dès que l'état de ce nœud change, nous le saurons. Et nous pouvons essayer d'avoir le temps de le recréer. Si nous avons pris ce nœud, pris ce verrou, alors une fois que nous n'aurons plus besoin du verrou, nous l'abandonnerons, car le nœud n'existe que dans la session. En conséquence, il disparaîtra. Et un autre client, dans le cadre d'une autre session, pourra prendre le verrou sur ce nœud, ou plutôt, il recevra une notification indiquant que quelque chose a changé et il pourra essayer de le faire à temps.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Un autre exemple de la façon dont vous pouvez choisir le leader principal. C'est un peu plus compliqué, mais aussi relativement simple. Que se passe t-il ici? Il existe un nœud principal qui regroupe tous les travailleurs. Nous essayons d'obtenir des données sur le leader. Si cela s'est produit avec succès, c'est-à-dire que nous avons reçu des données, alors notre travailleur commence à suivre ce leader. Il pense qu'il existe déjà un leader.

Si le leader est décédé pour une raison quelconque, par exemple s'il est tombé, nous essayons alors de créer un nouveau leader. Et si nous réussissons, alors notre travailleur devient le leader. Et si quelqu'un à ce moment-là réussissait à créer un nouveau leader, alors nous essayons de comprendre de qui il s'agit et ensuite de le suivre.

C'est ici qu'apparaît ce qu'on appelle l'effet de troupeau, c'est-à-dire l'effet de troupeau, car lorsqu'un leader meurt, celui qui est le premier dans le temps deviendra le leader.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Lors de la capture d'une ressource, vous pouvez essayer d'utiliser une approche légèrement différente, qui est la suivante. Par exemple, nous souhaitons obtenir un verrou, mais sans l'effet hert. Cela consistera dans le fait que notre application demande des listes de tous les identifiants de nœuds pour un nœud déjà existant avec un verrou. Et si avant cela le nœud pour lequel nous avons créé un verrou est le plus petit de l'ensemble que nous avons reçu, alors cela signifie que nous avons capturé le verrou. Nous vérifions que nous avons reçu un cadenas. À titre de contrôle, il y aura une condition selon laquelle l'identifiant que nous avons reçu lors de la création d'un nouveau verrou est minimal. Et si nous l'avons reçu, alors nous travaillons plus loin.

S'il existe un certain identifiant qui est plus petit que notre verrou, nous plaçons un observateur sur cet événement et attendons la notification jusqu'à ce que quelque chose change. Autrement dit, nous avons reçu ce verrou. Et jusqu'à ce qu'il tombe, nous ne deviendrons pas l'identifiant minimum et ne recevrons pas le verrou minimum, et ainsi nous pourrons nous connecter. Et si cette condition n'est pas remplie, alors nous allons immédiatement ici et essayons à nouveau d'obtenir ce verrou, car quelque chose a peut-être changé pendant ce temps.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

En quoi consiste ZooKeeper ? Il y a 4 choses principales. Il s'agit de processus de traitement - Demande. Et aussi ZooKeeper Atomic Broadcast. Il existe un journal de validation dans lequel toutes les opérations sont enregistrées. Et la base de données répliquée en mémoire elle-même, c'est-à-dire la base de données elle-même où toute cette arborescence est stockée.

Il convient de noter que toutes les opérations d’écriture passent par le processeur de requêtes. Et les opérations de lecture vont directement à la base de données en mémoire.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

La base de données elle-même est entièrement répliquée. Toutes les instances de ZooKeeper stockent une copie complète des données.

Afin de restaurer la base de données après un crash, il existe un journal de validation. La pratique standard est qu'avant que les données n'entrent en mémoire, elles y sont écrites afin qu'en cas de panne, ce journal puisse être lu et l'état du système puisse être restauré. Et des instantanés périodiques de la base de données sont également utilisés.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

ZooKeeper Atomic Broadcast est un élément utilisé pour conserver les données répliquées.

ZAB sélectionne en interne un leader du point de vue du nœud ZooKeeper. D'autres nœuds deviennent ses adeptes et attendent d'elle des actions. S'ils reçoivent des inscriptions, ils les transmettent toutes au leader. Il effectue d'abord une opération d'écriture, puis envoie un message sur ce qui a changé à ses abonnés. En fait, cela doit être effectué de manière atomique, c'est-à-dire que l'opération d'enregistrement et de diffusion de l'ensemble doit être effectuée de manière atomique, garantissant ainsi la cohérence des données.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop" Il traite uniquement les demandes d'écriture. Sa tâche principale est de transformer l'opération en une mise à jour transactionnelle. Il s'agit d'une demande spécialement générée.

Et ici, il convient de noter que l'idempotence des mises à jour pour une même opération est garantie. Ce que c'est? Cette chose, si elle est exécutée deux fois, aura le même état, c'est-à-dire que la requête elle-même ne changera pas. Et cela doit être fait pour qu'en cas de crash, vous puissiez redémarrer l'opération, annulant ainsi les modifications qui ont échoué pour le moment. Dans ce cas, l'état du système deviendra le même, c'est-à-dire qu'une série de processus identiques, par exemple des processus de mise à jour, ne devrait pas conduire à des états finaux différents du système.

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

« Hadoop. ZooKeeper" de la série Technostream du groupe Mail.Ru "Méthodes de traitement distribué de gros volumes de données dans Hadoop"

Source: habr.com

Ajouter un commentaire