
Bonjour, Habr!
Ce n'est pas un secret que d'énormes quantités de données sont impliquées dans le travail des applications modernes, et leur flux est en constante augmentation. Ces données doivent être stockées et traitées, souvent à partir d'un grand nombre de machines, et ce n'est pas une tâche facile. Pour le résoudre, il existe des magasins d'objets cloud. Il s'agit généralement d'une implémentation de la technologie de stockage défini par logiciel.
Début 2018, nous avons lancé (et lancé!) Notre propre stockage 100% compatible S3 basé sur Cloudian HyperStore. Il s'est avéré que le réseau a très peu de publications en russe sur Cloudian lui-même, et encore moins sur l'application réelle de cette solution.
Aujourd'hui, sur la base de l'expérience de DataLine, je vais vous parler de l'architecture et de la structure interne du logiciel Cloudian, y compris la mise en œuvre Cloudian SDS basée sur un certain nombre de solutions architecturales Apache Cassandra. Séparément, nous considérons le plus intéressant dans tout stockage SDS - la logique d'assurer la tolérance aux pannes et la distribution des objets.
Si vous construisez votre stockage S3 ou êtes occupé à le maintenir, cet article vous sera utile.
Tout d'abord, je vais vous expliquer pourquoi notre choix s'est porté sur Cloudian. C'est simple: il y a très peu d'options valables dans ce créneau. Par exemple, il y a quelques années, lorsque nous pensions à construire, il n'y avait que trois options:
- Passerelle CEHP + RADOS;
- Minio
- Cloudian HyperStore.
Pour nous, en tant que fournisseur de services, les facteurs décisifs ont été: un niveau élevé de correspondance entre l'API de stockage et l'Amazon S3 d'origine, la disponibilité de la facturation intégrée, l'évolutivité avec le support multirégionalité et la présence d'une troisième ligne de support fournisseur. Cloudian a tout cela.
Et oui, le plus (certainement!) La chose la plus importante est que DataLine et Cloudian ont des couleurs d'entreprise similaires. Vous devez admettre que nous n'avons pas pu résister à une telle beauté.

Malheureusement, Cloudian n'est pas le logiciel le plus courant, et il n'y a pratiquement aucune information à ce sujet dans RuNet. Aujourd'hui, nous allons corriger cette injustice et discuter avec vous des caractéristiques de l'architecture HyperStore, examiner ses composants les plus importants et traiter les principales nuances architecturales. Commençons par le plus élémentaire, à savoir - qu'est-ce que Cloudian sous le capot?
Fonctionnement du stockage Cloudian HyperStore
Jetons un coup d'œil au diagramme et voyons comment fonctionne la solution Cloudian.
Le schéma de stockage des composants principaux.Comme nous pouvons le voir, le système se compose de plusieurs composants principaux:
- Cloudian Management Control - console de gestion ;
- Service d'administration - module d'administration interne ;
- Service S3 - le module responsable de la prise en charge du protocole S3 ;
- Service HyperStore - le service de stockage réel ;
- Apache Cassandra - un référentiel centralisé de données de service ;
- Redis - pour les données les plus fréquemment lues .
Le plus grand intérêt pour nous sera le travail des principaux services, le service S3 et le service HyperStore, puis nous examinerons attentivement leur travail. Mais d'abord, il est logique de savoir comment la distribution des services dans le cluster est organisée et quelle est la tolérance aux pannes et la fiabilité du stockage des données de cette solution dans son ensemble.

Par
services communs dans le diagramme ci-dessus, nous entendons les
services S3, HyperStore, CMC et Apache Cassandra . À première vue, tout est beau et soigné. Mais en y regardant de plus près, il s'avère qu'une seule défaillance de nœud unique est effectivement résolue. Et la perte simultanée de deux nœuds à la fois peut être fatale pour la disponibilité du cluster - Redis QoS (sur le nœud 2) n'a qu'un seul esclave (sur le nœud 3). La même image avec le risque de perdre la gestion du cluster - Puppet Server n'est que sur deux nœuds (1 et 2). Cependant, la probabilité de défaillance de deux nœuds à la fois est très faible et vous pouvez vivre avec.
Néanmoins, pour augmenter la fiabilité du stockage, nous utilisons 4 nœuds dans la DataLine au lieu des trois minimum. La répartition des ressources suivante est obtenue:

Une nuance de plus frappe immédiatement: les
informations d'identification Redis ne
sont pas placées sur chaque nœud (comme on pourrait le supposer d'après le schéma officiel ci-dessus), mais seulement sur 3 d'entre elles. Dans ce cas,
Redis Credentials est utilisé pour chaque demande entrante. Il s'avère qu'en raison de la nécessité d'aller au Redis de quelqu'un d'autre, il y a un certain déséquilibre dans les performances du quatrième nœud.
Pour nous, ce n'est pas encore significatif. Pendant les tests de résistance, des écarts importants dans la vitesse de réponse des nœuds n'ont pas été remarqués, mais sur de grands groupes de dizaines de nœuds de travail, il est logique de corriger cette nuance.
Voici à quoi ressemble le schéma de migration sur 6 nœuds:
Le diagramme montre comment la migration des services est implémentée en cas de défaillance d'un nœud. Seule la panne d'un serveur de chaque rôle est prise en compte. Si les deux serveurs tombent, une intervention manuelle sera requise.Ici aussi, l'entreprise n'est pas sans subtilités. La migration des rôles utilise Puppet. Par conséquent, si vous le perdez ou le cassez accidentellement, le basculement automatique peut ne pas fonctionner. Pour la même raison, vous ne devez pas modifier manuellement le manifeste de la marionnette intégrée. Ce n'est pas entièrement sûr, les modifications peuvent être subitement effilochées, car les manifestes sont modifiés à l'aide du panneau d'administration du cluster.
Du point de vue de la sécurité des données, tout est beaucoup plus intéressant. Les métadonnées d'objet sont stockées dans Apache Cassandra et chaque enregistrement est répliqué sur 3 nœuds sur 4. Le facteur de réplication 3 est également utilisé pour stocker des données, mais vous pouvez en configurer un plus grand. Cela garantit la sécurité des données même en cas de défaillance simultanée de 2 nœuds sur 4. Et si vous avez le temps de rééquilibrer le cluster, vous ne pouvez rien perdre avec un nœud restant. L'essentiel est d'avoir suffisamment d'espace.
C'est ce qui se produit lorsque deux nœuds tombent en panne. Le diagramme montre clairement que même dans cette situation, les données restent en sécuritéDans le même temps, la disponibilité des données et du stockage dépendra de la stratégie visant à garantir la cohérence. Pour les données, les métadonnées, la lecture et l'écriture, il est configuré séparément.
Les options valides sont au moins un nœud, un quorum ou tous les nœuds.
Ce paramètre détermine le nombre de nœuds qui doivent confirmer l'écriture / la lecture pour que la demande soit considérée comme réussie. Nous utilisons le quorum comme compromis raisonnable entre le temps nécessaire au traitement d'une demande et la fiabilité de l'écriture / incohérence de lecture. Autrement dit, à partir des trois nœuds impliqués dans l'opération, pour un fonctionnement sans erreur, il suffit d'obtenir une réponse cohérente de 2. En conséquence, afin de rester à flot en cas de défaillance de plusieurs nœuds, vous devrez passer à une seule stratégie d'écriture / lecture.
Traitement des requêtes dans Cloudian
Ci-dessous, nous considérerons deux schémas de traitement des demandes entrantes dans Cloudian HyperStore, PUT et GET. Il s'agit de la tâche principale pour S3 Service et HyperStore.
Commençons par le traitement de la demande d'écriture:

Vous avez sûrement remarqué que chaque demande génère beaucoup de vérifications et de récupérations de données, au moins 6 hits d'un composant à l'autre. C'est à partir d'ici que les retards d'enregistrement et la consommation élevée de temps CPU apparaissent lorsque vous travaillez avec de petits fichiers.
Les fichiers volumineux sont transmis par morceaux. Les blocs séparés ne sont pas considérés comme des demandes distinctes et certains contrôles ne sont pas effectués.
Le nœud qui a reçu la demande initiale détermine en outre indépendamment où et quoi écrire, même s'il ne lui est pas écrit directement. Cela vous permet de masquer l'organisation interne du cluster du client final et d'utiliser des équilibreurs de charge externes. Tout cela affecte positivement la facilité de maintenance et la tolérance aux pannes du stockage.

Comme vous pouvez le voir, la logique de lecture n'est pas trop différente de l'écriture. On y observe la même sensibilité élevée de performance à la taille des objets traités. Par conséquent, en raison d'économies importantes dans l'utilisation des métadonnées, il est beaucoup plus facile d'extraire un objet finement haché que de nombreux objets distincts du même volume total.
Stockage et duplication de données
Comme vous pouvez le voir sur les diagrammes ci-dessus, Cloudian prend en charge divers schémas de stockage et de duplication de données:
Réplication - à l'aide de la réplication, il est possible de conserver un nombre personnalisé de copies de chaque objet de données dans le système et de stocker chaque copie sur différents nœuds. Par exemple, à l'aide de la réplication 3X, 3 copies de chaque objet sont créées et chaque copie «repose» sur son propre nœud.
Codage d' effacement - Avec le codage d'effacement, chaque objet est codé en une quantité personnalisée (connue sous le nom de numéro K) de fragments de données plus une quantité personnalisée de code de redondance (numéro M). Chaque fragment K + M d'un objet est unique et chaque fragment est stocké sur son propre nœud. Un objet peut être décodé à l'aide de n'importe quels fragments K. En d'autres termes, l'objet reste lisible, même si M nœuds sont inaccessibles.
Par exemple, dans le codage d'effacement, selon la formule 4 + 2 (4 fragments de données plus 2 fragments de code de redondance), chaque objet est divisé en 6 fragments uniques stockés sur six nœuds différents, et cet objet peut être restauré et lu si 4 fragments sur 6 sont disponibles .
L'avantage du codage d'effacement par rapport à la réplication est d'économiser de l'espace, mais au prix d'une augmentation significative de la charge du processeur, d'une détérioration de la vitesse de réponse et de la nécessité de procédures d'arrière-plan pour contrôler la cohérence des objets. Dans tous les cas, les métadonnées sont stockées séparément des données (dans Apache Cassandra), ce qui augmente la flexibilité et la fiabilité de la solution.
En bref sur les autres fonctions d'HyperStore
Comme je l'ai écrit au début de cet article, plusieurs outils utiles sont intégrés à HyperStore. Parmi eux:
- Facturation flexible avec prise en charge de la modification du prix d'une ressource en fonction du volume et du plan tarifaire;
- Surveillance intégrée
- La capacité de limiter l'utilisation des ressources pour les utilisateurs et les groupes d'utilisateurs;
- Paramètres QoS et procédures intégrées pour équilibrer l'utilisation des ressources entre les nœuds, ainsi que les procédures régulières de rééquilibrage entre les nœuds et les disques sur les nœuds ou lors de la saisie de nouveaux nœuds dans un cluster.
Cependant, Cloudian HyperStore n'est toujours pas parfait. Par exemple, pour une raison quelconque, vous ne pouvez pas transférer un compte existant vers un autre groupe ou affecter plusieurs groupes à un enregistrement. Il n'est pas possible de générer des rapports de facturation intermédiaires - vous ne recevrez tous les rapports qu'après la clôture de la période de rapport. Par conséquent, ni les clients ni nous ne pouvons savoir combien le compte a augmenté en temps réel.
Cloudian HyperStore Logic
Maintenant, nous allons plonger encore plus profondément et regarder le plus intéressant de tout stockage SDS - la logique de la distribution des objets par nœuds. Dans le cas du stockage Cloudian, les métadonnées sont stockées séparément des données elles-mêmes. Pour les métadonnées, Cassandra est utilisée, pour les données, la solution propriétaire HyperStore.
Malheureusement, jusqu'à présent, il n'y a pas de traduction officielle de la documentation de Cloudian en russe sur Internet, donc ci-dessous je publierai ma traduction des parties les plus intéressantes de cette documentation.
Le rôle d'Apache Cassandra dans HyperStore
Dans HyperStore, Cassandra est utilisée pour stocker les métadonnées d'objet, les informations de compte d'utilisateur et les données d'utilisation des services. Dans un déploiement typique sur chaque HyperStore, les données Cassandra sont stockées sur le même lecteur que le système d'exploitation. Le système prend également en charge les données Cassandra sur un lecteur dédié sur chaque nœud. Les données Cassandra ne sont pas stockées sur des disques de données HyperStore. Lorsque des vNodes sont attribués à l'hôte, ils sont distribués uniquement aux nœuds de stockage HyperStore. Les vNodes ne sont pas alloués au lecteur sur lequel les données Cassandra sont stockées.
À l'intérieur du cluster, les métadonnées de Cassandra sont répliquées conformément à la stratégie (stratégie) de votre référentiel. Cassandra Data Replication utilise les vNodes de cette façon:
- Lors de la création d'un nouvel objet Cassandra (clé primaire et ses valeurs correspondantes), il est haché et le hachage est utilisé pour associer l'objet à un vNode spécifique. Le système vérifie à quel hôte ce vNode est affecté, puis la première réplique de l'objet Cassandra est stockée sur le lecteur Cassandra sur cet hôte.
- Par exemple, supposons qu'un hôte se voit attribuer 96 vNodes répartis sur plusieurs disques de données HyperStore. Les objets Cassandra dont les valeurs de hachage se situent dans les plages de jetons de l'un de ces 96 vNodes seront écrits sur le lecteur Cassandra sur cet hôte.
- Des répliques supplémentaires de l'objet Cassandra (le nombre de répliques dépend de votre configuration) sont associées aux vNodes avec le numéro de séquence suivant et stockées sur le nœud auquel ces vNodes sont affectés, à condition que les vNodes soient ignorés si nécessaire, de sorte que chaque réplique de l'objet Cassandra soit stockée sur un autre machine hôte.
Fonctionnement du stockage HyperStore
Le placement et la réplication des objets S3 dans un cluster HyperStore sont basés sur un schéma de mise en cache cohérent qui utilise un espace de jeton entier compris entre 0 et 2
127 -1. Les jetons entiers sont affectés aux nœuds HyperStore. Pour chaque objet S3, un hachage est calculé lors de son chargement dans le stockage. L'objet est stocké dans le nœud auquel la valeur la plus faible du jeton a été affectée, supérieure ou égale à la valeur de hachage de l'objet. La réplication est également implémentée en stockant l'objet sur les nœuds auxquels des jetons ont été attribués, qui ont une valeur minimale.
Dans un stockage basé sur le hachage cohérent «classique», un jeton est attribué à un nœud physique. Le système Cloudian HyperStore utilise et étend les fonctionnalités du «nœud virtuel» (vNode) introduit dans Cassandra dans la version 1.2 - un grand nombre de jetons sont attribués à chaque hôte physique (256 au maximum). En fait, le cluster de stockage se compose d'un très grand nombre de «nœuds virtuels» avec un grand nombre de nœuds virtuels (jetons) sur chaque hôte physique.
Le système HyperStore attribue un ensemble distinct de jetons (nœuds virtuels) à chaque disque sur chaque hôte physique. Chaque disque sur l'hôte est responsable de son propre ensemble de répliques d'objets. Une défaillance de disque affecte uniquement les répliques d'objets qui s'y trouvent. Les autres lecteurs de l'hôte continueront de fonctionner et s'acquitteront de leurs responsabilités de stockage de données.
Nous donnons un exemple et considérons un cluster de 6 hôtes HyperStore, chacun ayant 4 disques de stockage S3. Supposons que 32 jetons sont attribués à chaque hôte physique et qu'il y ait un espace de jeton simplifié de 0 à 960, et la valeur de 192 jetons dans ce système (6 hôtes de 32 jetons) est de 0, 5, 10, 15, 20, etc. jusqu'à 955.
Le diagramme ci-dessous montre une distribution possible de jetons à travers le cluster. 32 jetons de chaque hôte sont répartis uniformément sur 4 disques (8 jetons par disque), et les jetons eux-mêmes sont répartis de manière aléatoire sur le cluster.

Supposons maintenant que vous ayez configuré HyperStore sur des objets S3 répliqués 3X. Soyons d'accord que l'objet S3 est chargé dans le système, et l'algorithme de hachage appliqué à son nom nous donne la valeur de hachage 322 (dans cet espace de hachage simplifié). Le diagramme ci-dessous montre comment trois instances ou répliques d'un objet seront stockées dans un cluster:
- Avec sa valeur de hachage de nom 322, la première réplique de l'objet est stockée sur 325 jetons, car il s'agit de la plus petite valeur de jeton supérieure ou égale à la valeur de hachage de l'objet. 325 jetons (surlignés en rouge sur le diagramme) sont affectés à hyperstore2: Disk2. En conséquence, la première réplique de l'objet y est stockée.
- La deuxième réplique est stockée sur le disque auquel est affecté le jeton suivant (330, surligné en orange), c'est-à-dire sur l'hyperstore4: Disk2.
- La troisième réplique est enregistrée sur le disque, à laquelle est attribué le jeton suivant après 330 - 335 (jaune), sur l'hyperstore3: Disk3.

J'ajouterai un commentaire: d'un point de vue pratique, cette optimisation (la distribution des jetons non seulement entre les nœuds physiques, mais aussi entre les disques individuels) est nécessaire non seulement pour assurer l'accessibilité, mais aussi pour assurer une distribution uniforme des données entre les disques. Dans ce cas, la matrice RAID n'est pas utilisée, toute la logique d'allocation des données sur les disques est contrôlée par HyperStore lui-même. D'une part, il est pratique et contrôlé; si un disque est perdu, tout sera rééquilibré indépendamment. D'un autre côté, je fais personnellement confiance à de meilleurs contrôleurs RAID - après tout, leur logique est optimisée depuis de nombreuses années. Mais ce sont toutes mes préférences personnelles, nous n'avons jamais attrapé HyperStore sur de vraies écoles et problèmes, si nous suivons les recommandations du fournisseur lors de l'installation de logiciels sur des serveurs physiques. Mais la tentative d'utiliser la virtualisation et les disques virtuels au-dessus de la même lune sur le système de stockage a échoué, lors de la surcharge du système de stockage pendant les tests de charge, HyperStore est devenu fou et a dispersé les données de manière totalement inégale, obstruant certains disques et n'en touchant pas d'autres.
Conduire le périphérique à l'intérieur d'un cluster
Rappelez-vous que chaque hôte possède 32 jetons et que les jetons de chaque hôte sont répartis uniformément entre ses disques. Examinons de plus près l'hyperstore2: Disk2 (dans le diagramme ci-dessous). Nous voyons que les jetons 325, 425, 370 et ainsi de suite sont affectés à ce disque.
Étant donné que le cluster est configuré pour la réplication 3X, les éléments suivants seront stockés sur hyperstore2: Disk2:
Conformément à 325 jetons de disque:
- Les premières répliques d'objets avec une valeur de hachage de 320 (exclusivement) à 325 (inclus);
- Deuxièmes répliques d'objets avec une valeur de hachage de 315 (exclusivement) à 320 (inclus);
- Troisièmes répliques d'objets avec une valeur de hachage de 310 (exclusivement) à 315 (inclus).
Selon le jeton de disque 425:
- Les premières répliques d'objets avec une valeur de hachage de 420 (exclusivement) à 425 (inclus);
- Deuxièmes répliques d'objets avec une valeur de hachage de 415 (exclusivement) à 420 (inclus);
- Troisièmes répliques d'objets avec une valeur de hachage de 410 (exclusivement) à 415 (inclus).
Et ainsi de suite.
Comme indiqué précédemment, lors du placement des deuxième et troisième répliques, HyperStore peut dans certains cas transmettre des jetons afin de ne pas stocker plus d'une copie de l'objet sur un nœud physique. Cela élimine l'utilisation d'hyperstore2: disk2 comme stockage pour les deuxième ou troisième répliques du même objet.

Si le disque 2 se bloque sur les disques 1, 3 et 4, les données continueront d'être stockées et les objets sur le disque 2 seront stockés dans le cluster, car ont été répliqués sur d'autres hôtes.
Commentaire: par conséquent, la distribution de répliques et / ou de fragments d'objets dans le cluster HyperStore est basée sur la conception de Cassandra, qui a été développée pour les besoins du stockage de fichiers. , , , , «» . . . , : , , .
Voyons maintenant comment fonctionne HyperStore dans plusieurs centres de données et régions. Dans notre cas, le mode multi-DPC diffère du mode multi-régional en utilisant un ou plusieurs espaces de jetons. Dans le premier cas, l'espace des jetons est uniforme. Dans la seconde, chaque région aura un espace de jeton indépendant avec (potentiellement) ses propres paramètres pour le niveau de cohérence, la capacité et les configurations de stockage.Pour comprendre comment cela fonctionne, revenons à la traduction de la documentation, section «Déploiements de centres de données multiples».Envisagez de déployer HyperStore dans deux centres de données. Appelez-les DC1 et DC2. Chaque centre de données dispose de 3 nœuds physiques. Comme dans nos exemples précédents, chaque nœud physique possède quatre disques, 32 jetons (vNodes) sont attribués à chaque hôte, et nous supposons un espace de jeton simplifié de 0 à 960. Selon ce scénario avec plusieurs centres de données, l'espace de jeton est divisé en 192 jetons - 32 jetons pour chacun des 6 hôtes physiques. Les jetons sont distribués par les hôtes de manière absolument aléatoire.Supposons également que la réplication des objets S3 dans ce cas est configurée sur deux répliques dans chaque centre de données.Voyons comment un objet S3 hypothétique avec une valeur de hachage de 942 se répliquera dans 2 centres de données:- vNode 945 ( ), DC2, hyperstore5:Disk3.
- vNode 950 ( ) DC2, hyperstore6:Disk4.
- vNode 955 DC2, , vNode .
- vNode 0 () — DC1, hyperstore2:Disk3. , (955) (0).
- vNode (5) DC2, , vNode .
- vNode 10 () — DC1, hyperstore3:Disk3.

: , , , , . , .
Ceci conclut notre présentation de l'architecture Cloudian et des fonctionnalités clés. Quoi qu'il en soit, ce sujet est trop sérieux et trop vaste pour intégrer le manuel exhaustif qu'il contient dans un article sur Habré. Par conséquent, si vous êtes intéressé par les détails que j'ai omis, vous avez des questions ou des suggestions pour la présentation du matériel dans les prochains articles, je me ferai un plaisir de communiquer avec vous dans les commentaires.Dans le prochain article, nous considérerons l'implémentation du stockage S3 dans DataLine, nous parlerons en détail des technologies d'infrastructure et de tolérance aux pannes de réseau utilisées, et en bonus, je vous raconterai l'histoire de sa construction!