Mysql
 sql >> Base de données >  >> RDS >> Mysql

Un guide pour comprendre les modèles de mise à l'échelle de la base de données

Il existe de nombreux articles en ligne décrivant les modèles d'évolutivité des bases de données, mais il s'agit pour la plupart d'articles dispersés - uniquement des techniques définies au hasard sans trop de contexte. Je trouve qu'ils ne sont pas définis étape par étape, et je ne discute pas du moment où choisir l'option de mise à l'échelle, quelles options de mise à l'échelle sont réalisables dans la pratique et pourquoi.

Par conséquent, je prévois de discuter de certaines des techniques en détail dans de futurs articles. Pour commencer, je pense que c'est mieux si je discute des techniques étape par étape avec un peu de contexte à ma manière. Cet article est un article de haut niveau - je ne discuterai pas des techniques de mise à l'échelle en détail ici, mais je fournirai un aperçu. Alors commençons.

Une étude de cas

Supposons que vous ayez créé une startup qui propose du covoiturage à moindre coût. Au départ lorsque vous démarrez, vous ciblez une ville et avez à peine des dizaines de clients après votre annonce initiale.

Vous enregistrez tous les clients, trajets, emplacements, données de réservation et historique des trajets des clients dans la même base de données ou très probablement sur une seule machine physique. Il n'y a pas de mise en cache sophistiquée ou de pipeline de données volumineuses pour résoudre les problèmes, car votre application est très récente. C'est parfait pour votre cas d'utilisation en ce moment car il y a très peu de clients et votre système réserve à peine 1 trajet en 5 minutes, par exemple.

Mais au fil du temps, de plus en plus de personnes commencent à s'inscrire sur votre système puisque vous êtes le service le moins cher du marché et grâce à votre promotion et à vos publicités. Vous commencez à réserver, disons, 10 réservations par minute, et lentement le nombre augmente à 20, 30 réservations par minute.

À ce stade, vous vous rendez compte que le système a commencé à mal fonctionner :la latence de l'API a beaucoup augmenté, et certaines transactions se bloquent ou s'affament et finissent par échouer. Votre application met plus de temps à répondre, ce qui provoque l'insatisfaction des clients. Que pouvez-vous faire pour résoudre le problème ?

Modèle 1 - Optimisation des requêtes et mise en œuvre du pool de connexions :

La première solution qui vient à l'esprit est que le cache utilise fréquemment des données non dynamiques comme l'historique des réservations, l'historique des paiements, les profils des utilisateurs, etc. Mais après cette mise en cache de la couche d'application, vous ne pouvez pas résoudre le problème de latence des API exposant des données dynamiques telles que l'emplacement actuel du conducteur ou les taxis les plus proches pour un client donné ou le coût actuel du trajet à un certain moment après le début du trajet.

Vous identifiez que votre base de données est probablement fortement normalisée, vous introduisez donc des colonnes redondantes (ces colonnes apparaissent fréquemment dans WHERE ou JOIN ON clause dans les requêtes) dans les tables très utilisées à des fins de dénormalisation. Cela réduit les requêtes de jointure, divise une grande requête en plusieurs requêtes plus petites et ajoute leurs résultats dans la couche d'application.

Une autre optimisation parallèle que vous pouvez effectuer consiste à modifier les connexions à la base de données. Les bibliothèques clientes de base de données et les bibliothèques externes sont disponibles dans presque tous les langages de programmation. Vous pouvez utiliser des bibliothèques de pools de connexions pour mettre en cache les connexions à la base de données ou configurer la taille du pool de connexions dans le système de gestion de base de données lui-même.

La création d'une connexion réseau est coûteuse car elle nécessite une communication aller-retour entre le client et le serveur. Le regroupement des connexions peut vous aider à optimiser le nombre de connexions. Les bibliothèques de pool de connexions peuvent vous aider à multiplexer les connexions - plusieurs threads d'application peuvent utiliser la même connexion à la base de données. Je verrai si je peux expliquer en détail la mise en commun des connexions dans un article séparé plus tard.

Vous mesurez la latence de vos API et trouvez probablement une latence réduite de 20 à 50 % ou plus. C'est une bonne optimisation pour le moment.

Vous avez maintenant étendu votre entreprise à une ville de plus, plus de clients s'inscrivent, vous commencez lentement à faire 80 à 100 réservations par minute. Votre système n'est pas en mesure de gérer cette échelle. Encore une fois, vous voyez que la latence de l'API a augmenté, que la couche de base de données a abandonné, mais cette fois, aucune optimisation des requêtes ne vous donne un gain de performances significatif. Vous vérifiez la métrique du système, vous constatez que l'espace disque est presque plein, que le processeur est occupé 80 % du temps, que la RAM se remplit très rapidement.

Modèle 2 - Mise à l'échelle verticale ou mise à l'échelle :

Après avoir examiné toutes les métriques du système, vous savez qu'il n'y a pas d'autre solution facile que de mettre à niveau le matériel du système. Vous mettez à niveau votre taille de RAM de 2 fois, mettez à niveau l'espace disque de, disons, 3 fois ou plus. C'est ce qu'on appelle la mise à l'échelle verticale ou la mise à l'échelle de votre système. Vous informez votre équipe d'infrastructure ou votre équipe de devops ou des agents tiers du centre de données pour mettre à niveau votre machine.

Mais comment configurez-vous la machine pour la mise à l'échelle verticale ?

Vous allouez une plus grande machine. Une approche consiste à ne pas migrer les données manuellement depuis l'ancienne machine, mais plutôt à définir la nouvelle machine comme replica à la machine existante (primary )-créer un primary replica temporaire configuration. Laissez la réplication se faire naturellement. Une fois la réplication terminée, promouvez la nouvelle machine en tant que machine principale et mettez l'ancienne machine hors ligne. Étant donné que la plus grande machine est censée répondre à toutes les requêtes, toutes les lectures / écritures se produiront sur cette machine.

Frais. Votre système est à nouveau opérationnel avec des performances accrues.

Votre entreprise se porte très bien et vous décidez de passer à 3 villes supplémentaires - vous êtes maintenant opérationnel dans 5 villes au total. Le trafic est 3 fois plus élevé qu'auparavant, vous êtes censé faire environ 300 réservations par minute. Avant même d'atteindre cet objectif de réservation, vous rencontrez à nouveau un problème de performances, la taille de l'index de la base de données augmente considérablement en mémoire, elle nécessite une maintenance constante, l'analyse des tables avec index devient plus lente que jamais. Vous calculez le coût d'une mise à l'échelle supplémentaire de la machine, mais vous n'êtes pas convaincu du coût. Que faites-vous maintenant ?

Modèle 3 - Ségrégation de la responsabilité des requêtes de commande (CQRS) :

Vous identifiez que la grosse machine n'est pas capable de gérer tout le read/write demandes. De plus, dans la plupart des cas, toute entreprise a besoin d'une capacité transactionnelle sur write mais pas sur read opérations. Vous êtes également d'accord avec un peu de read incohérente ou retardée opérations et votre entreprise n'a aucun problème avec cela non plus. Vous voyez une opportunité où il pourrait être une bonne option de séparer le read &write opérations physiques machine sage. Cela permettra aux machines individuelles de gérer plus de read/write opérations.

Vous prenez maintenant deux autres grosses machines et les configurez en tant que replica à la machine actuelle. La réplication de la base de données se chargera de distribuer les données de primary machine à replica Machines. Vous parcourez toutes les requêtes de lecture (Query (Q ) dans CQRS ) aux répliques — n'importe quelle replica peut répondre à n'importe quelle requête de lecture, vous naviguez dans toutes les requêtes d'écriture (Commande (C ) dans CQRS ) au primary . Il peut y avoir peu de décalage dans la réplication, mais selon votre cas d'utilisation, c'est très bien.

La plupart des startups de taille moyenne qui traitent chaque jour quelques centaines de milliers de requêtes peuvent survivre avec une configuration de réplica principal à condition qu'elles archivent périodiquement les données plus anciennes.

Maintenant que vous passez à 2 autres villes, vous voyez que votre primary n'est pas capable de gérer tous les write demandes. Beaucoup write les demandes ont de la latence. De plus, le décalage entre primary &replica ont parfois un impact sur les clients et les chauffeurs, par exemple :lorsque le voyage se termine, le client paie le chauffeur avec succès, mais le chauffeur ne peut pas voir le paiement car l'activité du client est une write requête qui va au primary , tandis que l'activité du conducteur est une read requête qui va à l'un des réplicas. Votre système global est si lent que le conducteur ne peut pas voir le paiement pendant au moins une demi-minute, ce qui est frustrant pour le conducteur et le client. Comment le résolvez-vous ?

Modèle 4 - Réplication multi-primaire

Vous avez très bien évolué avec primary-replica configuration, mais vous avez maintenant besoin de plus de performances en écriture. Vous pourriez être prêt à faire un petit compromis sur read demander des performances. Pourquoi ne pas distribuer la requête d'écriture à un replica aussi ?

Dans un multi-primary configuration, toutes les machines peuvent fonctionner à la fois comme primary &replica . Vous pouvez penser à multi-primary comme un cercle de machines dit A->B->C->D->A . B peut répliquer les données de A , C peut répliquer les données de B , D peut répliquer les données de C , A peut répliquer les données de D . Vous pouvez écrire des données sur n'importe quel nœud, tout en lisant des données, vous pouvez diffuser la requête à tous les nœuds, celui qui répond le renvoie. Tous les nœuds auront le même schéma de base de données, le même ensemble de tables, l'index, etc. Vous devez donc vous assurer qu'il n'y a pas de collision dans id entre les nœuds de la même table, sinon lors de la diffusion, plusieurs nœuds renverraient des données différentes pour le même id .

Généralement, il est préférable d'utiliser UUID ou GUID pour identifiant. Un autre inconvénient de cette technique est — read les requêtes peuvent être inefficaces car elles impliquent la diffusion de la requête et l'obtention du résultat correct - essentiellement une approche de collecte par dispersion.

Maintenant, vous passez à 5 villes supplémentaires et votre système souffre à nouveau. On s'attend à ce que vous traitiez environ 50 requêtes par seconde. Vous avez désespérément besoin de gérer un grand nombre de demandes simultanées. Comment y parvenir ?

Modèle 5 - Partitionnement :

Vous savez que votre location la base de données est quelque chose qui devient élevé write &read Circulation. Probablement write:read le rapport est 7:3 . Cela met beaucoup de pression sur les bases de données existantes. Le location les tables contiennent peu de données primaires comme longitude , latitude , timestamp , driver id , trip id etc. Cela n'a pas grand-chose à voir avec les déplacements des utilisateurs, les données des utilisateurs, les données de paiement, etc. Qu'en est-il de la séparation de l'location tables dans un schéma de base de données séparé ? Qu'en est-il de mettre cette base de données dans des machines séparées avec le bon primary-replica ou multi-primary configuration?

C'est ce qu'on appelle le partitionnement des données par fonctionnalité. Différentes bases de données peuvent héberger des données classées par différentes fonctionnalités, si nécessaire, le résultat peut être agrégé dans la couche principale. En utilisant cette technique, vous pouvez vous concentrer sur la mise à l'échelle de ces fonctionnalités qui exigent un niveau élevé de read/write demandes. Bien que le back-end ou la couche d'application doive assumer la responsabilité de joindre les résultats si nécessaire, ce qui entraînera probablement davantage de modifications de code.

Imaginez maintenant que vous avez étendu votre entreprise à un total de 20 villes dans votre pays et que vous envisagez de vous étendre bientôt en Australie. Votre demande croissante d'application nécessite une réponse plus rapide et plus rapide. Aucune des méthodes ci-dessus ne peut vous aider à l'extrême maintenant. Vous devez faire évoluer votre système de manière à ce que l'expansion vers d'autres pays/régions ne nécessite pas toujours que vous procédiez à des changements d'ingénierie ou d'architecture fréquents. Comment faites-vous cela ?

Modèle 6 - Mise à l'échelle horizontale :

Vous faites beaucoup de recherches sur Google, lisez beaucoup sur la façon dont d'autres entreprises ont résolu le problème - et arrivez à la conclusion que vous devez évoluer horizontalement. Vous allouez, par exemple, 50 machines - toutes ont le même schéma de base de données qui à son tour contient le même ensemble de tables. Toutes les machines ne contiennent qu'une partie des données.

Étant donné que toutes les bases de données contiennent le même ensemble de tables, vous pouvez concevoir le système de manière à ce que la localité des données soit là, c'est-à-dire; toutes les données associées atterrissent dans la même machine. Chaque machine peut avoir ses propres répliques, les répliques peuvent être utilisées dans la récupération après panne. Chacune des bases de données est appelée shard . Une machine physique peut avoir un ou plusieurs shards - c'est à vous de concevoir comme vous le souhaitez. Vous devez choisir la sharding key de telle manière qu'une seule sharding key fait toujours référence à la même machine. Vous pouvez donc imaginer de nombreuses machines contenant toutes des données associées dans le même ensemble de tables, read/write requêtes pour la même ligne ou le même ensemble de terrains de ressources dans la même machine de base de données.

Le sharding est en général difficile - du moins les ingénieurs de différentes entreprises le disent. Mais lorsque vous traitez des millions ou des milliards de demandes, vous devez prendre une décision difficile.

Je vais discuter du sharding plus en détail dans mon prochain article, retenant ainsi ma tentation d'en discuter davantage dans cet article.

Maintenant que vous avez mis en place le partage, vous êtes sûr de pouvoir évoluer dans de nombreux pays. Votre entreprise a tellement grandi que les investisseurs vous poussent à faire évoluer l'entreprise sur tous les continents. Vous voyez à nouveau un problème ici. La latence de l'API à nouveau. Votre service est hébergé aux États-Unis et les Vietnamiens ont du mal à réserver des trajets. Pourquoi? Que faites-vous à ce sujet ?

Modèle 7 - Partition Wise du centre de données :

Votre entreprise se développe en Amérique, en Asie du Sud et dans quelques pays d'Europe. Vous faites des millions de réservations quotidiennement avec des milliards de requêtes sur votre serveur. Félicitations - c'est un moment fort pour votre entreprise.

Mais comme les demandes de l'application doivent voyager à travers les continents via des centaines ou des milliers de serveurs sur Internet, la latence augmente. Qu'en est-il de la répartition du trafic entre les centres de données ? Vous pouvez configurer un centre de données à Singapour qui gère toutes les demandes en provenance d'Asie du Sud, un centre de données en Allemagne peut gérer toutes les demandes des pays européens et un centre de données en Californie peut gérer toutes les demandes des États-Unis.

Vous activez également la réplication entre centres de données, ce qui facilite la reprise après sinistre. Ainsi, si le centre de données californien effectue une réplication vers le centre de données de Singapour, en cas de panne du centre de données californien en raison d'un problème d'électricité ou d'une calamité naturelle, toutes les demandes des États-Unis peuvent être renvoyées au centre de données de Singapour, etc.

Cette technique de mise à l'échelle est utile lorsque vous avez des millions de clients à desservir dans tous les pays et que vous ne pouvez pas gérer la perte de données, vous devez toujours maintenir la disponibilité du système.

Voici quelques techniques générales étape par étape pour la mise à l'échelle de la base de données. Bien que la plupart des ingénieurs n'aient pas assez de chance de mettre en œuvre ces techniques, mais dans l'ensemble, il est préférable d'avoir une idée plus large d'un tel système qui, à l'avenir, pourrait vous aider à améliorer la conception du système et de l'architecture.

Dans mes prochains articles, je vais essayer de discuter de certains concepts en détail. N'hésitez pas à donner des commentaires appropriés pour ce message, le cas échéant.

L'article est initialement publié sur le compte média de l'auteur :https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522