• Assurez la sécurité des applications de la bonne manière! Détectez, protégez, surveillez, accélérez et plus encore…
  • Comment faire évoluer MongoDB? Quelles sont les meilleures pratiques de partitionnement?

    Alors que le schéma flexible est la façon dont la plupart des gens se familiarisent avec MongoDB, c'est aussi l'une des meilleures bases de données (peut-être même le idéal pour les applications quotidiennes) pour la gestion de très, très grands ensembles de données. Alors que la justification de cet argument appelle un article entier en soi (j'espère pouvoir trouver du temps pour cela un jour!), L'idée générale est que les solutions basées sur SQL ne prennent pas en charge le sharding, et le construire sur votre base est nul.

    Le mieux que vous puissiez espérer est de créer un cluster (ce qui n'a fondamentalement rien à voir avec le sharding, soit dit en passant) ou d'opter pour une solution gérée comme le RDS d'Amazon ou le Cloud SQL de Google, qui deviennent prohibitifs à mesure que vos données augmentent.

    Dans cet article, nous examinerons l'une des techniques essentielles pour mise à l'échelle horizontale de la base de données: partitionnement, pour MongoDB, et recommandent quelques bonnes pratiques pour le même. Cependant, je pense qu'il vaut mieux commencer par les bases du sharding, car de nombreuses personnes qui cherchent à faire évoluer MongoDB ne le connaissent peut-être pas très bien.

    Cependant, si vous êtes conscient du sharding, n'hésitez pas à parcourir la section suivante.

    Principes de base du partage

    Vous avez peut-être remarqué l'utilisation du mot «horizontal» dans le dernier paragraphe de la section précédente. Sans me lancer dans un autre détour massif, je souhaite aborder ce point rapidement. La mise à l'échelle envisage d'être de deux types: vous obtenez soit une machine plus puissante avec une capacité de stockage plus élevée (verticale), ou vous connectez plusieurs ordinateurs plus petits et formez une collection (horizontal).

    Maintenant, étant donné que même les meilleurs serveurs à l'heure actuelle ne disposent pas de plus de 256 Go de RAM ou 16 To de disque dur, vous vous heurtez rapidement à un mur de briques en essayant de faire évoluer verticalement (ou «scale up», selon la terminologie). Cependant, vous pouvez connecter autant de machines individuelles ensemble (au moins théoriquement) et contourner facilement cette limitation.

    Bien sûr, le défi est maintenant de coordonner entre toutes ces machines.

    Partage de base de données

    Le terme «sharding» s'applique généralement aux bases de données, l'idée étant qu'une seule machine ne peut jamais suffire à contenir toutes les données. Lors du partitionnement, la base de données est «décomposée» en blocs distincts qui résident sur différentes machines. Un exemple simple pourrait être: supposons qu'une entreprise dispose de machines capables de stocker jusqu'à 2 millions d'éléments de données client. Aujourd'hui, l'entreprise atteint ce point de rupture et dépassera probablement bientôt 2.5 millions d'utilisateurs. Alors, ils décident de diviser leur base de données en deux:

    Et comme par magie, la capacité du système est maintenant doublée!

    Eh bien, si seulement la vie était aussi simple! 🙂

    Défis du partitionnement de base de données

    Dès que vous avez réfléchi un peu plus au sharding, des défis infâmes surgissent de leur horrible tête.

    Aucune clé primaire

    Dès que vous sortez d'une seule base de données, les clés primaires perdent leur signification. Par exemple, si vos clés primaires sont définies sur l'incrémentation automatique et que vous déplacez la moitié des données vers une autre base de données, vous aurez désormais deux éléments de données différents pour chaque clé primaire.

    Aucune clé étrangère

    Comme il n'y a pas de support dans les bases de données pour pointer vers des entités en dehors de la base de données actuelle (enfin, même une base de données différente sur la même machine n'est pas prise en charge, alors oubliez une base de données sur un différent machine), le concept de clés étrangères vaut également pour un tirage au sort. Soudainement, la base de données devient «stupide» et l'intégrité des données est votre problème.

    Erreurs de données étranges

    Si une seule machine s'éteint, l'utilisateur final peut recevoir un message "Oups, quelque chose est cassé!" page, ce qui va sans doute ennuyer, mais la vie sera sur la bonne voie après un certain temps.

    Considérez maintenant ce qui se passe dans une base de données fragmentée. Supposons que la base de données fragmentée de notre exemple précédent soit une base de données bancaire et qu'un client envoie de l'argent à un autre. Supposons également que les premières données client vivent dans le premier fragment, tandis que les données du deuxième client vivent dans le deuxième fragment (vous voyez où je veux en venir?!). Si la machine contenant le deuxième fragment tombe en panne, pouvez-vous imaginer dans quel état le système sera? Où ira l'argent de la transaction? Que verra le premier utilisateur? Que verra le deuxième utilisateur? Que verront-ils tous les deux lorsque les fragments seront de nouveau en ligne?

    Gestion des transactions

    Prenons également le cas toujours critique de la gestion des transactions. Cette fois, supposons que le système fonctionne à 100% correctement. Maintenant, deux personnes (A et B) effectuent un paiement à une troisième (C). Il est très probable que les deux transactions liront simultanément le solde du compte de C, provoquant cette confusion:

    • Solde du compte de C = 100 $.
    • La transaction de A lit le solde de C: 100 $.
    • La transaction de B lit le solde de C: 100 $.
    • La transaction de A ajoute 50 $ et met à jour le solde: 100 $ + 50 = 150 $.
    • La transaction de B ajoute 50 $ et met à jour le solde: 100 $ + 50 = 150 $.

    Zut! 50 $ ont juste disparu dans les airs!

    Les systèmes SQL traditionnels vous en épargnent en fournissant une gestion intégrée des transactions, mais dès que vous sortez d'une seule machine, vous êtes trinqué.

    Le fait est qu'avec de tels systèmes, il est facile de rencontrer des problèmes de corruption de données dont il est impossible de récupérer. Tirer vos cheveux n'aidera pas non plus! 🙂

    Partage MongoDB

    Pour les architectes logiciels, l'enthousiasme suscité par MongoDB n'était pas tant dans son schéma flexible que dans sa prise en charge intégrée du sharding. Avec seulement quelques règles simples et des machines connectées, vous étiez prêt à exécuter un cluster MongoDB fragmenté en un rien de temps.

    L'image ci-dessous montre à quoi cela ressemble dans un déploiement d'application Web typique.

    Crédit d'image: mongodb.com

    La meilleure partie du sharding MongoDB est que même l'équilibrage des fragments est automatique. Autrement dit, si vous avez cinq fragments et que deux d'entre eux sont presque vides, vous pouvez dire à MongoDB de rééquilibrer les choses de manière à ce que tous les fragments soient également pleins.

    En tant que développeur ou administrateur, vous n'avez pas à vous inquiéter beaucoup, car MongoDB dans les coulisses fait l'essentiel du travail. Il en va de même pour la défaillance partielle des nœuds; si vous avez des jeux de réplicas correctement configurés et en cours d'exécution sur votre cluster, les pannes partielles n'affecteront pas la disponibilité du système.

    L'explication entière serait plutôt brève, je vais donc fermer cette section en disant que MongoDB dispose de plusieurs outils intégrés pour le partitionnement, la réplication et la récupération, ce qui permet aux développeurs de créer très facilement des applications à grande échelle. Si vous souhaitez un guide plus complet des capacités de partitionnement de MongoDB, le documents officiels sont l'endroit où être.

    Consultez ce guide pratique pour implémenter le partage. Cela pourrait également vous intéresser guide complet du développeur.

    Meilleures pratiques de partage de MongoDB

    Bien que MongoDB «fonctionne tout simplement» pour le sharding, cela ne signifie pas que nous pouvons nous reposer sur nos lauriers. Le partage peut faire ou défaire votre projet pour toujours, selon la façon dont il a été réalisé ou mal réalisé.

    De plus, il y a beaucoup de petits détails à prendre en compte, faute de quoi, il n'est pas rare de voir des projets s'effondrer. L'intention n'est pas de vous faire peur, mais de souligner la nécessité de planifier et d'être extrêmement prudent même avec de petites décisions.

    La clé de partage contrôle inévitablement le partitionnement dans MongoDB, il est donc idéal que nous commencions notre enquête avec cela.

    Cardinalité élevée

    La cardinalité signifie la quantité de variation. Par exemple, une collection d'un pays préféré de 1 million de personnes aura de faibles variations (il n'y a que tellement de pays dans le monde!), Alors qu'une collection de leurs adresses e-mail aura (parfaitement) une cardinalité élevée. Pourquoi est-ce important? Supposons que vous choisissiez un schéma naïf qui fragmente les données en fonction du prénom d'un utilisateur.

    Ici, nous avons une disposition assez simple; le document entrant est scanné pour le nom d'utilisateur, et selon l'emplacement de la première lettre dans l'alphabet anglais, il atterrit dans l'un des trois fragments. De même, la recherche d'un document est facile: les détails de «Peter», par exemple, seront certainement dans le deuxième fragment.

    Tout cela semble bien, mais le fait est que nous ne contrôlons pas les noms des utilisateurs de documents entrants. Et si nous n'obtenions que des noms dans la plage B à F la plupart du temps? Si c'est le cas, nous aurons ce qu'on appelle un morceau «jumbo» dans shard1: la plupart des données système y seront entassées, transformant ainsi la configuration en un système de base de données unique.

    Le traitement?

    Choisissez une clé avec une cardinalité élevée - par exemple, l'adresse e-mail des utilisateurs, ou vous pouvez même opter pour une clé de partition composée, qui est une combinaison de plusieurs champs.

    Changement monotone

    Une erreur courante dans le partitionnement MongoDB est d'utiliser des clés à augmentation monotone (ou à augmentation automatique, si vous voulez) comme clé de partition.

    Généralement, la clé primaire du document est utilisée. L'idée ici est bien intentionnée, à savoir qu'au fur et à mesure que de nouveaux documents se créent, ils tomberont uniformément dans l'un des fragments disponibles. Malheureusement, une telle configuration est une erreur classique. Cela est dû au fait que si la clé de partition augmente toujours, après un point, les données commenceront à s'accumuler du côté à valeur élevée des fragments, provoquant un déséquilibre dans le système.

    Crédit d'image: mongodb.com

    Comme vous pouvez le voir sur l'image, une fois que nous avons dépassé la plage 20, tous les documents commencent à être collectés dans le bloc C, provoquant un monolithe. La solution consiste à opter pour un schéma de clé de partitionnement haché, qui crée une clé de partitionnement en hachant l'un des champs fournis et en l'utilisant pour déterminer le morceau.

    Crédit d'image: Mongodb.com

    Une clé de partition hachée ressemble à ceci:

     {"_id": "6b85117af532da651cc912cd"}

    . . . et peut être créé dans le shell client Mongo en utilisant:

     db.collection.createIndex ({_id: hashedValue})

    Éclat tôt

    L'un des conseils les plus utiles provenant directement des tranchées est de fragmenter tôt, même si vous vous retrouvez avec un petit cluster à deux morceaux. Une fois que les données ont franchi 500 Go ou quelque chose du genre, le sharding devient un processus compliqué dans MongoDB, et vous devriez être prêt pour de mauvaises surprises. En outre, le processus de rééquilibrage consomme de très grandes quantités de bande passante réseau, ce qui peut étrangler le système si vous ne faites pas attention.

    Cependant, tout le monde n'est pas pro-sharding. A titre d'exemple intéressant (l'apprentissage est vraiment dans les commentaires), voyez ce joli Percona blog.

    Exécution de l'équilibreur

    Une autre bonne idée est de surveiller vos modèles de trafic et d'exécuter l'équilibreur de partition uniquement aux heures de faible trafic. Comme je l'ai déjà mentionné, le rééquilibrage lui-même prend une bande passante considérable, ce qui pourrait rapidement amener l'ensemble du système à une analyse. N'oubliez pas que les éclats déséquilibrés ne sont pas une cause de panique immédiate. Laissez simplement l'utilisation normale persister, attendez les opportunités à faible trafic et laissez l'équilibreur faire le reste!

    Voici comment vous pouvez y parvenir (en supposant que vous ayez un faible trafic de 3 h à 5 h):

     utilisez la configuration db.settings.update ({_id: "balancer"}, {$ set: {activeWindow: {start: "03:00", stop: "05:00"}}}, {upsert: true})

    Conclusion

    Le partage et la mise à l'échelle de toute base de données est une entreprise délicate, mais heureusement, MongoDB la rend plus gérable que d'autres bases de données populaires.

    Il fut en effet un temps où MongoDB n'était pas le bon choix pour aucun projet (grâce à ses nombreux problèmes critiques et comportements par défaut), mais ceux-ci ont disparu depuis longtemps. Avec le sharding, le rééquilibrage, la compression automatique, le verrouillage distribué au niveau agrégé et de nombreuses fonctionnalités similaires, MongoDB a parcouru des kilomètres en avance et est aujourd'hui le premier choix de l'architecte logiciel.

    J'espère que cet article a été en mesure de faire la lumière sur ce qu'est le sharding dans MongoDB et ce que le développeur doit prendre en compte lors de la mise à l'échelle. Ensuite, familiarisez-vous avec les Commandes MongoDB.