web-dev-qa-db-fra.com

Approches de partage de MySQL?

Quelle est la meilleure approche pour Sharding MySQL tables. Les approches auxquelles je peux penser sont:

  1. Partage de niveau d'application?
  2. Partage sur la couche proxy MySQL?
  3. Serveur de recherche central pour le sharding?

Connaissez-vous des projets ou des outils intéressants dans ce domaine?

85
sheki

La meilleure approche pour partitionner des tables MySQL pour ne pas le faire à moins qu'il ne soit totalement inévitable de le faire.

Lorsque vous écrivez une application, vous voulez généralement le faire de manière à maximiser la vitesse, la vitesse du développeur. Vous optimisez la latence (temps jusqu'à ce que la réponse soit prête) ou le débit (nombre de réponses par unité de temps) uniquement lorsque cela est nécessaire.

Vous partitionnez puis attribuez des partitions à différents hôtes (= partition) uniquement lorsque la somme de toutes ces partitions ne tient plus sur une seule instance de serveur de base de données - la raison en étant soit en écriture, soit en lecture.

Le cas d'écriture est soit a) la fréquence des écritures surcharge les disques de ce serveur en permanence, soit b) il y a trop d'écritures en cours pour que la réplication soit en retard dans cette hiérarchie de réplication.

Le cas de lecture pour le partitionnement est lorsque la taille des données est si grande que leur ensemble de travail ne tient plus dans la mémoire et que les lectures de données commencent à frapper le disque au lieu d'être servies à partir de la mémoire la plupart du temps.

Ce n'est que lorsque vous avez à partager que vous le faites.


Au moment où vous partagez, vous payez pour cela de plusieurs façons:

Une grande partie de votre SQL n'est plus déclarative.

Normalement, en SQL, vous dites à la base de données quelles données vous voulez et laissez à l'optimiseur le soin de transformer cette spécification en un programme d'accès aux données. C'est une bonne chose, car elle est flexible et parce que l'écriture de ces programmes d'accès aux données est un travail ennuyeux qui nuit à la vitesse.

Avec un environnement fragmenté, vous joignez probablement une table sur le nœud A à des données sur le nœud B, ou vous avez une table plus grande qu'un nœud, sur les nœuds A et B et vous joignez des données de celle-ci à des données qui se trouvent sur les nœuds B et C. Vous commencez à écrire manuellement des résolutions de jointure basées sur le hachage côté application afin de résoudre cela (ou vous réinventez le cluster MySQL), ce qui signifie que vous vous retrouvez avec beaucoup de SQL qui n'est plus déclaratif, mais qui exprime la fonctionnalité SQL de manière procédurale (par exemple, vous utilisez des instructions SELECT dans des boucles).

Vous subissez beaucoup de latence du réseau.

Normalement, une requête SQL peut être résolue localement et l'optimiseur connaît les coûts associés aux accès au disque local et résout la requête d'une manière qui minimise les coûts pour cela.

Dans un environnement fragmenté, les requêtes sont résolues en exécutant des accès par valeur-clé sur un réseau à plusieurs nœuds (avec des accès par clé groupés et non des recherches de clés individuelles par aller-retour) ou en poussant des parties de la clause WHERE vers l'avant aux nœuds où ils peuvent être appliqués (c'est-à-dire "refoulement de condition"), ou les deux.

Mais même dans le meilleur des cas, cela implique beaucoup plus de voyages aller-retour sur le réseau qu'une situation locale, et c'est plus compliqué. Surtout que l'optimiseur MySQL ne sait rien du tout sur la latence du réseau (Ok, le cluster MySQL s'améliore lentement, mais pour Vanilla MySQL en dehors du cluster, c'est toujours vrai).

Vous perdez beaucoup de puissance expressive de SQL.

Ok, c'est probablement moins important, mais les contraintes de clé étrangère et les autres mécanismes SQL pour l'intégrité des données sont incapables de s'étendre sur plusieurs fragments.

MySQL n'a pas d'API qui autorise les requêtes asynchrones en état de marche.

Lorsque des données du même type résident sur plusieurs nœuds (par exemple, les données utilisateur sur les nœuds A, B et C), les requêtes horizontales doivent souvent être résolues par rapport à tous ces nœuds ("Rechercher tous les comptes d'utilisateurs qui ne sont pas connectés depuis 90 jours ou plus"). Le temps d'accès aux données croît de façon linéaire avec le nombre de nœuds, à moins que plusieurs nœuds puissent être demandés en parallèle et les résultats agrégés au fur et à mesure ("Map-Reduce").

La condition préalable à cela est une API de communication asynchrone, qui n'existe pas pour MySQL en bon état de fonctionnement. L'alternative est beaucoup de fourches et de connexions dans les processus enfants, qui visitent le monde de sucer sur un abonnement de saison.


Une fois que vous avez commencé le partage, la structure des données et la topologie du réseau deviennent visibles lorsque les performances pointent vers votre application. Afin de fonctionner raisonnablement bien, votre application doit être consciente de ces choses, et cela signifie que seul le partage de niveau d'application a du sens.

La question est plus si vous voulez un partitionnement automatique (déterminer quelle ligne va dans quel nœud en hachant les clés primaires par exemple) ou si vous voulez diviser fonctionnellement de manière manuelle ("Les tables liées à la user story xyz vont à ce master, tandis que les tables liées à abc et def vont à ce master ").

Le sharding fonctionnel a l'avantage que, s'il est bien fait, il est invisible pour la plupart des développeurs la plupart du temps, car toutes les tables liées à leur user story seront disponibles localement. Cela leur permet de bénéficier du SQL déclaratif aussi longtemps que possible et entraîne également moins de latence du réseau car le nombre de transferts entre réseaux reste minimal.

Le partitionnement fonctionnel présente l'inconvénient de ne pas permettre à une seule table d'être plus grande qu'une instance, et cela nécessite une attention manuelle d'un concepteur.

Le partage fonctionnel a l'avantage de pouvoir être effectué relativement facilement sur une base de code existante avec un certain nombre de modifications qui ne sont pas trop importantes. http://Booking.com l'a fait plusieurs fois au cours des dernières années et cela a bien fonctionné pour eux.


Cela dit, au vu de votre question, je crois que vous posez les mauvaises questions, ou je ne comprends absolument pas votre énoncé du problème.

107
Isotopp
  1. Partage au niveau de l'application: dbShards est le seul produit que je connaisse à faire un "partage sensible aux applications". Il y a quelques bons articles sur le site Web. Juste par définition, le partage des applications va être plus efficace. Si une application sait exactement où aller avec une transaction sans avoir à la rechercher ou à être redirigée par un proxy, cela en soi sera plus rapide. Et la vitesse est souvent l'une des principales préoccupations, sinon la seule, lorsque quelqu'un se penche sur le sharding.

  2. Certaines personnes "éclatent" avec un proxy, mais à mes yeux, cela va à l'encontre du but du sharding. Vous utilisez simplement un autre serveur pour indiquer à vos transactions où trouver les données ou où les stocker. Grâce au partage des applications, votre application sait où aller d'elle-même. Beaucoup plus efficace.

  3. C'est vraiment la même chose que # 2.

10
chantheman

Connaissez-vous des projets ou des outils intéressants dans ce domaine?

Plusieurs nouveaux projets dans cet espace:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/Twitter/gizzard/
7
btcbb

Shard-Query est une solution de partitionnement basée sur OLAP pour MySQL. Il vous permet de définir une combinaison de tables fragmentées et de tables non fragmentées. Les tables non fragmentées (comme les tables de recherche) peuvent être librement jointes à des tables fragmentées, et les tables fragmentées peuvent être jointes les unes aux autres tant que les tables sont jointes par la clé de partition (pas de partition croisée ou d'auto-jointure qui traversent les limites de la partition). Étant une solution OLAP, Shard-Query a généralement des temps de réponse minimum de 100 ms ou moins, même pour les requêtes simples, donc cela ne fonctionnera pas pour OLTP. Shard-Query est conçu pour analyser des ensembles de données volumineuses en parallèle.

Il existe également des solutions de partitionnement OLTP pour MySQL. Les solutions en source fermée incluent ScaleDB , DBShards . Open source OLTP solution inclut JetPants , Cubrid ou Flock/Gizzard (infrastructure Twitter).

4
Justin Swanhart

Niveau d'application bien sûr.

La meilleure approche que j'ai jamais trouvée dans ce livre

MySQL haute performance http://www.Amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

Brève description: vous pouvez diviser vos données en plusieurs parties et stocker environ 50 parties sur chaque serveur. Cela vous aidera à éviter le deuxième plus gros problème de partage - le rééquilibrage. Déplacez simplement certains d'entre eux vers le nouveau serveur et tout ira bien :)

Je vous recommande fortement de l'acheter et de lire la partie "scaling mysql".

3
Andrey Frolov

En 2018, il semble y avoir une solution native MySql à cela. Il y a en fait au moins 2 - cluster InnoDB et cluster NDB (il existe une version commerciale et une version communautaire).

Étant donné que la plupart des personnes qui utilisent l'édition communautaire MySql connaissent mieux le moteur InnoDB, c'est ce qui devrait être exploré en priorité. Il prend en charge la réplication et le partitionnement/sharding hors de la boîte et est basé sur MySql Router pour différentes options de routage/équilibrage de charge.

La syntaxe pour la création de vos tables devrait changer, par exemple:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(ce n'est qu'un des quatre types de partitionnement )

Une limitation très importante:

Les clés étrangères InnoDB et le partitionnement MySQL ne sont pas compatibles. Les tables InnoDB partitionnées ne peuvent pas avoir de références de clé étrangère, ni de colonnes référencées par des clés étrangères. Les tables InnoDB qui ont ou qui sont référencées par des clés étrangères ne peuvent pas être partitionnées.

2
yuranos87