Architecture et fonctionnalités de Tarantool Data Grid



En 2017, nous avons remporté le concours pour le développement du cœur transactionnel des activités d'investissement d'Alfa Bank et commencé à travailler (à HighLoad ++ 2018 , Vladimir Drynkin, responsable du cœur transactionnel des activités d'investissement d'Alfa Bank, a présenté un rapport sur le cœur des activités d'investissement). Ce système consistait à regrouper les données de transaction provenant de diverses sources dans différents formats, à rassembler les données sous une forme unifiée, à les enregistrer et à y accéder.

Au cours du développement, le système a évolué et est devenu fonctionnel, et à un moment donné, nous avons réalisé que nous cristallisions quelque chose de bien plus qu'un simple logiciel d'application conçu pour résoudre une gamme de tâches strictement définie: nous avons obtenu un système pour construire des applications distribuées avec stockage persistant . Notre expérience a constitué la base d'un nouveau produit - Tarantool Data Grid (TDG).

Je veux parler de l'architecture TDG et des solutions que nous avons imaginées au cours du processus de développement, vous présenter les fonctionnalités de base et montrer comment notre produit peut devenir la base de la construction de solutions complètes.

Sur le plan architectural, nous avons divisé le système en rôles distincts, chacun étant chargé de résoudre un certain éventail de tâches. Une instance en cours d'exécution d'une application implémente un ou plusieurs types de rôles. Un cluster peut avoir plusieurs rôles du même type:



Connecteur


Le connecteur est responsable de la communication avec le monde extérieur; sa tâche consiste à accepter la requête, à l'analyser et, si elle réussit, à envoyer les données pour traitement au processeur d'entrée. Nous prenons en charge les formats HTTP, SOAP, Kafka, FIX. L'architecture vous permet d'ajouter simplement la prise en charge de nouveaux formats, la prise en charge IBM MQ arrive bientôt. Si l'analyse de la demande a échoué, le connecteur renvoie une erreur; sinon, il répondra que la demande a été traitée avec succès, même si une erreur s'est produite lors de son traitement ultérieur. Ceci est fait exprès, afin de travailler avec des systèmes qui ne savent pas répéter les demandes - ou vice versa, faites-le trop agressivement. Afin de ne pas perdre de données, une file d'attente de réparation est utilisée: l'objet y entre d'abord et seulement après que le traitement réussi en ait été supprimé. L'administrateur peut recevoir des notifications concernant les objets restant dans la file d'attente de réparation et après avoir éliminé une erreur logicielle ou une défaillance matérielle, réessayez.

Processeur d'entrée


Le processeur d'entrée classe les données reçues par caractéristique et appelle les gestionnaires appropriés. Les gestionnaires sont du code Lua qui s'exécute dans le bac à sable, ils ne peuvent donc pas affecter le fonctionnement du système. À ce stade, les données peuvent être réduites à la forme souhaitée et, si nécessaire, exécuter un nombre arbitraire de tâches pouvant implémenter la logique nécessaire. Par exemple, dans le produit MDM (Master Data Management) construit sur la grille de données Tarantool, lors de l'ajout d'un nouvel utilisateur, nous exécutons une tâche distincte afin de ne pas ralentir le traitement de la demande. Le bac à sable prend en charge les demandes de lecture, de modification et d'ajout de données; il vous permet d'effectuer certaines fonctions sur tous les rôles tels que le stockage et d'agréger le résultat (mapper / réduire).

Les gestionnaires peuvent être décrits dans des fichiers:

sum.lua local x, y = unpack(...) return x + y 

Et puis, déclaré dans la configuration:

 functions: sum: { __file: sum.lua } 

Pourquoi Lua? Lua est une langue très simple. D'après notre expérience, quelques heures après l'avoir rencontré, les gens commencent à écrire du code qui résout leur problème. Et ce ne sont pas seulement des développeurs professionnels, mais par exemple des analystes. De plus, grâce au compilateur jit, Lua est très rapide.

Stockage


Le stockage stocke des données persistantes. Avant l'enregistrement, les données sont validées pour la conformité avec le schéma de données. Pour décrire le schéma, nous utilisons le format étendu Apache Avro . Un exemple:

 { "name": "User", "type": "record", "logicalType": "Aggregate", "fields": [ { "name": "id", "type": "string"}, {"name": "first_name", "type": "string"}, {"name": "last_name", "type": "string"} ], "indexes": ["id"] } 

Sur la base de cette description, DDL (Data Definition Language) pour Tarantula DBMS et le schéma GraphQL pour l'accès aux données sont générés automatiquement.

La réplication de données asynchrone est prise en charge (prévoit d'ajouter synchrone).

Processeur de sortie


Parfois, il est nécessaire d'informer les consommateurs externes de l'arrivée de nouvelles données, pour cela il y a le rôle du processeur de sortie. Après avoir enregistré les données, elles peuvent être transférées vers le gestionnaire approprié (par exemple, pour les amener à la forme requise par le consommateur) - puis transférées vers le connecteur pour l'envoi. La file d'attente de réparation est également utilisée ici: si personne n'a accepté l'objet, l'administrateur peut réessayer plus tard.

Mise à l'échelle


Les rôles du connecteur, du processeur d'entrée et du processeur de sortie sont sans état, ce qui nous permet de faire évoluer le système horizontalement, en ajoutant simplement de nouvelles instances de l'application avec le rôle inclus du type souhaité. Pour la mise à l'échelle du stockage horizontal, une approche de l'organisation des clusters à l'aide de compartiments virtuels est utilisée. Après avoir ajouté un nouveau serveur, une partie du compartiment des anciens serveurs en arrière-plan se déplace vers le nouveau serveur; cela se produit de manière transparente pour les utilisateurs et n'affecte pas le fonctionnement de l'ensemble du système.

Propriétés des données


Les objets peuvent être très grands et contenir d'autres objets. Nous garantissons l'atomicité de l'ajout et de la mise à jour des données, en sauvegardant l'objet avec toutes les dépendances sur un seul compartiment virtuel. Cela élimine le "maculage" de l'objet sur plusieurs serveurs physiques.

La gestion des versions est prise en charge: chaque mise à jour de l'objet crée une nouvelle version, et nous pouvons toujours créer une tranche de temps et voir à quoi ressemblait alors le monde. Pour les données qui n'ont pas besoin d'un long historique, nous pouvons limiter le nombre de versions ou même n'en stocker qu'une seule - la dernière - c'est-à-dire désactiver réellement la gestion des versions pour un certain type. Vous pouvez également limiter l'historique par le temps: par exemple, supprimez tous les objets d'un certain type de plus d'un an. L'archivage est également pris en charge: nous pouvons décharger des objets plus anciens que l'heure spécifiée, libérant ainsi de l'espace dans le cluster.

Les tâches


Parmi les fonctions intéressantes, il convient de noter la possibilité d'exécuter des tâches selon un calendrier, à la demande de l'utilisateur ou par programmation à partir du sandbox:



Ici, nous voyons un autre rôle - coureur. Ce rôle n'a pas d'état et, si nécessaire, des instances d'application supplémentaires avec ce rôle peuvent être ajoutées au cluster. La responsabilité du coureur est de terminer les tâches. Comme indiqué, la création de nouvelles tâches à partir du bac à sable est possible; ils sont mis en file d'attente sur le stockage, puis exécutés sur le coureur. Ce type de tâche s'appelle Job. Nous avons également un type de tâche appelé Tâche - ce sont des tâches définies par l'utilisateur qui sont planifiées pour s'exécuter (en utilisant la syntaxe cron) ou à la demande. Pour exécuter et suivre ces tâches, nous avons un gestionnaire de tâches pratique. Pour que cette fonctionnalité soit disponible, vous devez activer le rôle de planificateur; ce rôle a un état, donc il n'est pas évolutif, ce qui n'est cependant pas requis; cependant, comme tous les autres rôles, elle peut avoir une réplique qui commence à fonctionner si le maître refuse soudainement.

Enregistreur


Un autre rôle est appelé enregistreur. Il collecte les journaux de tous les membres du cluster et fournit une interface pour les télécharger et les visualiser via une interface Web.

Les services


Il convient de mentionner que le système facilite la création de services. Dans le fichier de configuration, vous pouvez spécifier les demandes à envoyer au gestionnaire écrit par l'utilisateur s'exécutant dans le sandbox. Dans ce gestionnaire, vous pouvez, par exemple, exécuter une sorte de requête analytique et renvoyer le résultat.

Le service est décrit dans le fichier de configuration:

 services: sum: doc: "adds two numbers" function: sum return_type: int args: x: int y: int 

L'API GraphQL est générée automatiquement et le service devient disponible pour appeler:

 query { sum(x: 1, y: 2) } 

Cela appellera le gestionnaire de sum , qui renverra le résultat:

 3 

Profilage et métriques des requêtes


Pour comprendre le profilage du système et des requêtes, nous avons implémenté la prise en charge du protocole OpenTracing. Le système peut, sur demande, envoyer des informations à des outils qui prennent en charge ce protocole, par exemple Zipkin, qui vous permettra de comprendre comment la demande a été exécutée:



Naturellement, le système fournit des métriques internes qui peuvent être collectées à l'aide de Prometheus et visualisées à l'aide de Grafana.

Déployer


Tarantool Data Grid peut être déployé à partir de packages ou d'archives RPM, en utilisant l'utilitaire de la livraison ou Ansible, il existe également un support pour Kubernetes ( Tarantool Kubernetes Operator ).

Une application qui implémente la logique métier (configuration, processeurs) est chargée dans le cluster Tarantool Data Grid sous forme d'archive via l'interface utilisateur ou à l'aide d'un script via l'API fournie par nous.

Exemples d'application


Quelles applications puis-je créer avec Tarantool Data Grid? En fait, la plupart des tâches métier sont en quelque sorte liées au traitement du flux de données, à son stockage et à son accès. Par conséquent, si vous avez de grands flux de données qui doivent être stockés en toute sécurité et y avoir accès, notre produit peut vous faire gagner beaucoup de temps dans le développement et vous concentrer sur votre logique métier.

Par exemple, nous souhaitons collecter des informations sur le marché immobilier afin par la suite, par exemple, d'avoir des informations sur les meilleures offres. Dans ce cas, nous distinguons les tâches suivantes:

  1. Des robots collectant des informations à partir de sources ouvertes - ce seront nos sources de données. Vous pouvez résoudre ce problème en utilisant des solutions toutes faites ou en écrivant du code dans n'importe quelle langue.
  2. Ensuite, la grille de données Tarantool acceptera et enregistrera les données. Si le format des données provenant de différentes sources est différent, vous pouvez écrire du code dans le langage Lua, ce qui conduira à la conversion en un seul format. Au stade du prétraitement, vous pouvez également, par exemple, filtrer les offres récurrentes ou mettre à jour en outre des informations sur les agents opérant sur le marché dans la base de données.
  3. Maintenant, vous avez déjà une solution évolutive dans le cluster, qui peut être remplie de données et faire des échantillons de données. Ensuite, vous pouvez implémenter de nouvelles fonctionnalités, par exemple, écrire un service qui interrogera les données et émettra l'offre la plus rentable en une journée - cela nécessitera quelques lignes dans le fichier de configuration et un peu de code Lua.

Et ensuite?


Notre priorité est d'augmenter la facilité de développement avec la grille de données Tarantool . Par exemple, il s'agit d'un IDE avec prise en charge du profilage et du débogage des gestionnaires en bac à sable.

Nous accordons également une grande attention aux problèmes de sécurité. À l'heure actuelle, nous passons la certification FSTEC Russie pour confirmer le haut niveau de sécurité et répondre aux exigences de certification des produits logiciels utilisés dans les systèmes d'information sur les données personnelles et les systèmes d'information d'État.

Source: https://habr.com/ru/post/fr466155/


All Articles