Comment arrêter de s'inquiéter et commencer à vivre sans monolithe

Comment arrêter de s'inquiéter et commencer à vivre sans monolithe

Nous aimons tous les histoires. Nous aimons nous asseoir autour du feu et parler de nos victoires passées, de nos batailles ou simplement de notre expérience professionnelle.

Aujourd’hui est un tel jour. Et même si vous n’êtes pas au coin du feu en ce moment, nous avons une histoire pour vous. L'histoire de la façon dont nous avons commencé à travailler avec le stockage sur Tarantool.

Il était une fois notre entreprise avait quelques « monolithes » et un « plafond » pour tous, vers lesquels ces monolithes se rapprochaient lentement mais sûrement, limitant le vol de notre entreprise, notre développement. Et il y avait une compréhension claire : un jour, nous atteindrons durement ce plafond.

L’idéologie dominante consiste désormais à séparer tout et tout le monde, de l’équipement à la logique métier. De ce fait, nous disposons par exemple de deux DC pratiquement indépendants au niveau du réseau. Et puis tout était complètement différent.

Aujourd'hui, il existe de nombreux outils et outils pour effectuer des modifications sous forme de CI/CD, K8S, etc. À l’époque « monolithique », nous n’avions pas besoin d’autant de mots étrangers. Il suffisait simplement de corriger le « stockage » dans la base de données.

Mais le temps a avancé, et le nombre de demandes a augmenté avec lui, poussant parfois les RPS au-delà de nos capacités. Avec l'entrée des pays de la CEI sur le marché, la charge sur le processeur de base de données du premier monolithe n'est pas tombée en dessous de 90 % et le RPS est resté au niveau de 2400 XNUMX. Et ce n'étaient pas seulement de petits sélecteurs, mais de lourdes requêtes avec un un ensemble de contrôles et de JOIN qui pourraient exécuter près de la moitié des données dans le contexte d'E/S volumineuses.

Lorsque les ventes à part entière du Black Friday ont commencé à apparaître - et Wildberries a été l'un des premiers à les organiser en Russie - la situation est devenue complètement triste. Après tout, la charge ces jours-là augmente trois fois.
Oh, ces « temps monolithiques » ! Je suis sûr que vous avez vécu quelque chose de similaire et que vous ne comprenez toujours pas comment cela a pu vous arriver.

Que pouvez-vous faire : la mode est inhérente à la technologie. Il y a environ 5 ans, nous avons dû repenser l'un de ces mods sous la forme d'un site existant sur un serveur .NET et MS SQL, qui stockait soigneusement toute la logique du site lui-même. Je l'ai gardé si soigneusement que scier un tel monolithe s'est avéré être un plaisir long et pas du tout facile.
Une petite digression.

Lors de divers événements, je dis : « Si vous n'avez pas vu de monolithe, alors vous n'avez pas grandi ! » Je suis intéressé par votre avis à ce sujet, veuillez l'écrire dans les commentaires.

Et le tonnerre a frappé

Revenons à notre "feu de joie". Pour répartir la charge de fonctionnalités « monolithiques », nous avons décidé de diviser le système en microservices basés sur des technologies open source. Parce qu’au minimum, leur mise à l’échelle est moins coûteuse. Et nous savions à 100 % que nous devions évoluer (et beaucoup). Après tout, déjà à cette époque, il était possible d'accéder aux marchés des pays voisins et le nombre d'enregistrements ainsi que le nombre de commandes ont commencé à croître encore plus fortement.

Après avoir analysé les premiers candidats au passage du monolithe aux microservices, nous nous sommes rendu compte que 80 % des écrits qu'ils contiennent proviennent des systèmes de back-office, et la lecture du front-office. Tout d'abord, cela concernait quelques sous-systèmes importants pour nous - les données des utilisateurs et un système de calcul du coût final des marchandises basé sur des informations sur les remises et coupons supplémentaires pour les clients.

Dentelé. Maintenant, c'est effrayant à imaginer, mais en plus des sous-systèmes mentionnés ci-dessus, les catalogues de produits, le panier d'achat des utilisateurs, le système de recherche de produits, le système de filtrage des catalogues de produits et divers types de systèmes de recommandation ont également été supprimés de notre monolithe. Pour le fonctionnement de chacun d'eux, il existe des classes distinctes de systèmes étroitement adaptés, mais autrefois, ils vivaient tous dans une seule « maison ».

Nous avons immédiatement prévu de transférer les données de nos clients vers le système fragmenté. La suppression de la fonctionnalité de calcul du coût final des marchandises nécessitait une bonne évolutivité pour la lecture, car elle créait la plus grande charge RPS et était la plus difficile à mettre en œuvre pour la base de données (de nombreuses données sont impliquées dans le processus de calcul).

En conséquence, nous avons mis au point un schéma qui correspond bien à Tarantool.

A cette époque, pour le fonctionnement des microservices, des schémas permettant de travailler avec plusieurs centres de données sur des machines virtuelles et matérielles ont été choisis. Comme le montrent les figures, les options de réplication Tarantool ont été appliquées en modes maître-maître et maître-esclave.

Comment arrêter de s'inquiéter et commencer à vivre sans monolithe
Architecture. Option 1. Service utilisateur

À l'heure actuelle, il existe 24 fragments, chacun comportant 2 instances (une pour chaque DC), le tout en mode maître-maître.

Au-dessus de la base de données se trouvent les applications qui accèdent aux répliques de la base de données. Les applications fonctionnent avec Tarantool via notre bibliothèque personnalisée, qui implémente l'interface du pilote Tarantool Go. Elle voit toutes les répliques et peut travailler avec le maître pour lire et écrire. Essentiellement, il implémente le modèle de jeu de réplicas, qui ajoute une logique pour sélectionner les réplicas, effectuer des tentatives, un disjoncteur et une limite de débit.

Dans ce cas, il est possible de configurer la politique de sélection des réplicas dans le contexte des fragments. Par exemple, roundrobin.

Comment arrêter de s'inquiéter et commencer à vivre sans monolithe
Architecture. Option 2. Service de calcul du coût final des marchandises

Il y a quelques mois, la plupart des demandes de calcul du coût final des marchandises étaient adressées à un nouveau service qui, en principe, fonctionne sans bases de données, mais il y a quelque temps, tout était traité à 100 % par un service avec Tarantool sous le capot.

La base de données de service se compose de 4 maîtres dans lesquels le synchroniseur collecte des données, et chacun de ces maîtres de réplication distribue les données aux répliques en lecture seule. Chaque maître possède environ 15 répliques de ce type.

Que ce soit dans le premier ou dans le deuxième schéma, si un contrôleur de domaine n'est pas disponible, l'application peut recevoir des données dans le second.

Il convient de noter que la réplication dans Tarantool est assez flexible et peut être configurée au moment de l'exécution. Dans d'autres systèmes, des difficultés sont apparues. Par exemple, la modification des paramètres max_wal_senders et max_replication_slots dans PostgreSQL nécessite un redémarrage de l'assistant, ce qui dans certains cas peut conduire à la rupture des connexions entre l'application et le SGBD.

Rechercher et trouver!

Pourquoi ne l’avons-nous pas fait « comme des gens normaux », mais choisi une manière atypique ? Cela dépend de ce qui est considéré comme normal. De nombreuses personnes créent généralement un cluster à partir de Mongo et le répartissent sur trois contrôleurs de domaine géo-distribués.

A cette époque, nous avions déjà deux projets Redis. Le premier était un cache et le second était un stockage persistant pour les données pas trop critiques. C'était assez difficile avec lui, en partie à cause de notre faute. Parfois, des volumes assez importants étaient à la clé et, de temps en temps, le site devenait malade. Nous avons utilisé ce système dans la version maître-esclave. Et il y a eu de nombreux cas où quelque chose est arrivé au maître et la réplication a échoué.

Autrement dit, Redis convient aux tâches sans état, pas aux tâches avec état. En principe, cela permettait de résoudre la plupart des problèmes, mais seulement s'il s'agissait de solutions clé-valeur avec une paire d'index. Mais Redis à cette époque était assez triste en termes de persistance et de réplication. De plus, des plaintes ont été déposées concernant les performances.

Nous avons pensé à MySQL et PostgreSQL. Mais le premier ne nous a pas vraiment convaincu, et le second est un produit plutôt sophistiqué en soi, et il serait inapproprié de construire des services simples dessus.
Nous avons essayé RIAK, Cassandra et même une base de données graphique. Ce sont toutes des solutions assez niches qui ne convenaient pas au rôle d'outil universel général de création de services.

Finalement, nous avons opté pour Tarantool.

Nous nous y sommes tournés lorsqu'il était en version 1.6. Nous nous y sommes intéressés par la symbiose clé-valeur et la fonctionnalité d'une base de données relationnelle. Il existe des index secondaires, des transactions et des espaces, ils sont comme des tables, mais pas simples, vous pouvez y stocker différents nombres de colonnes. Mais la fonctionnalité phare de Tarantool était les index secondaires combinés à la valeur-clé et à la transactionnalité.

La communauté russophone réactive, prête à aider dans le chat, a également joué un rôle. Nous l'avons activement utilisé et vivons directement dans le chat. Et n’oubliez pas une persévérance décente, sans erreurs ni erreurs évidentes. Si vous regardez notre historique avec Tarantool, nous avons eu beaucoup de problèmes et d'échecs avec la réplication, mais nous n'avons jamais perdu de données à cause de sa faute !

La mise en œuvre a connu un début difficile

À cette époque, notre principale pile de développement était .NET, pour laquelle il n’existait aucun connecteur pour Tarantool. Nous avons immédiatement commencé à faire quelque chose dans Go. Cela a également bien fonctionné avec Lua. Le principal problème à cette époque était celui du débogage : dans .NET, tout va bien avec ça, mais après cela, il était difficile de plonger dans le monde de Lua embarqué, quand on n'a pas de débogage à part les logs. De plus, pour une raison quelconque, la réplication s'effondrait périodiquement, j'ai donc dû me plonger dans la structure du moteur Tarantool. Le chat nous a aidé, et dans une moindre mesure, la documentation ; parfois nous regardions le code. À cette époque, la documentation était médiocre.

Ainsi, au cours de plusieurs mois, j'ai réussi à comprendre et à obtenir des résultats décents en travaillant avec Tarantool. Nous avons compilé des développements de référence dans git qui ont aidé à la formation de nouveaux microservices. Par exemple, lorsqu'une tâche se présentait : créer un autre microservice, le développeur regardait le code source de la solution de référence dans le référentiel, et il ne lui fallait pas plus d'une semaine pour en créer un nouveau.

C’étaient des moments particuliers. Classiquement, vous pouvez alors vous adresser à l'administrateur à la table voisine et lui demander : "Donnez-moi une machine virtuelle". Une trentaine de minutes plus tard, la voiture était déjà chez vous. Vous vous êtes connecté, avez tout installé et le trafic vous a été envoyé.

Aujourd'hui, cela ne fonctionnera plus : il faut ajouter du monitoring et de la journalisation au service, couvrir les fonctionnalités avec des tests, commander une machine virtuelle ou la livrer à Kuber, etc. En général, ce sera mieux ainsi, même si cela prendra plus de temps et sera plus gênant.

Diviser pour régner. Quel est le problème avec Lua ?

Il y avait un sérieux dilemme : certaines équipes étaient incapables de déployer de manière fiable les modifications d'un service avec beaucoup de logique dans Lua. Cela s’accompagnait souvent d’un dysfonctionnement du service.

Autrement dit, les développeurs préparent une sorte de changement. Tarantool commence à effectuer la migration, mais la réplique contient toujours l'ancien code ; Un DDL ou autre chose y arrive via la réplication, et le code s'effondre simplement car il n'est pas pris en compte. En conséquence, la procédure de mise à jour pour les administrateurs a été présentée sur une feuille A4 : arrêter la réplication, mettre à jour ceci, activer la réplication, éteindre ici, mettre à jour là. Cauchemar!

En conséquence, nous essayons désormais le plus souvent de ne rien faire en Lua. Utilisez simplement iproto (un protocole binaire pour interagir avec le serveur), et c'est tout. Il s’agit peut-être d’un manque de connaissances de la part des développeurs, mais de ce point de vue, le système est complexe.

Nous ne suivons pas toujours aveuglément ce scénario. Aujourd'hui, nous n'avons pas de noir et blanc : soit tout est en Lua, soit tout est en Go. Nous comprenons déjà comment les combiner pour ne pas nous retrouver plus tard avec des problèmes de migration.

Où est Tarantool maintenant ?
Tarantool est utilisé dans le service de calcul du coût final des marchandises en tenant compte des coupons de réduction, également appelé « Promoteur ». Comme je l'ai dit plus tôt, il prend désormais sa retraite : il est remplacé par un nouveau service de catalogue avec des prix pré-calculés, mais il y a six mois, tous les calculs étaient effectués dans Promotizer. Auparavant, la moitié de sa logique était écrite en Lua. Il y a deux ans, le service a été transformé en espace de stockage, et la logique a été réécrite en Go, car la mécanique des remises avait un peu changé et le service manquait de performance.

L'un des services les plus critiques est le profil utilisateur. Autrement dit, tous les utilisateurs de Wildberries sont stockés dans Tarantool, et il y en a environ 50 millions. Un système fragmenté par ID utilisateur, réparti sur plusieurs DC connectés aux services Go.
Selon RPS, Promoter était autrefois le leader, atteignant 6 50 demandes. À un moment donné, nous en avions 60 à 12 exemplaires. Aujourd'hui, le leader du RPS est celui des profils d'utilisateurs, environ 20 4. Ce service utilise un partitionnement personnalisé, divisé par plages d'ID utilisateur. Le service dessert plus de 5 machines, mais c'est trop, nous prévoyons de réduire les ressources allouées, car la capacité de XNUMX à XNUMX machines lui suffit.

Le service de session est notre premier service sur vshard et Cartouche. La configuration de vshard et la mise à jour de Cartouche nous ont demandé quelques efforts, mais au final, tout s'est bien passé.

Le service d'affichage de différentes bannières sur le site et dans l'application mobile a été l'un des premiers à être lancé directement sur Tarantool. Ce service se distingue par le fait qu'il a 6-7 ans, qu'il est toujours opérationnel et n'a jamais été redémarré. La réplication maître-maître a été utilisée. Rien n'est jamais cassé.

Il existe un exemple d'utilisation de Tarantool pour la fonctionnalité de référence rapide dans un système d'entrepôt afin de vérifier rapidement les informations dans certains cas. Nous avons essayé d'utiliser Redis pour cela, mais les données en mémoire occupaient plus d'espace que Tarantool.

Les services de liste d'attente, d'abonnements clients, d'histoires à la mode et de marchandises différées fonctionnent également avec Tarantool. Le dernier service en mémoire occupe environ 120 Go. Il s’agit du service le plus complet de ce qui précède.

Conclusion

Grâce aux index secondaires combinés à la clé-valeur et à la transactionnalité, Tarantool est bien adapté aux architectures basées sur des microservices. Cependant, nous avons rencontré des difficultés lors du déploiement des modifications apportées aux services avec beaucoup de logique dans Lua - les services cessaient souvent de fonctionner. Nous n'avons pas pu surmonter cela et, au fil du temps, nous sommes arrivés à différentes combinaisons de Lua et Go : nous savons où utiliser une langue et où en utiliser une autre.

Quoi d'autre à lire sur le sujet

Source: habr.com

Ajouter un commentaire