Bases de données en master – master

J’ai cher­ché de quoi stocker des données avec plusieurs serveurs maîtres en répli­ca­tion, mais je n’ai rien trouvé d’in­té­res­sant pour l’ins­tant. Je me suis dis que toi, fidèle lecteur, tu pour­rais appor­ter ta pierre. D’au­tant qu’il me semble que c’est une problé­ma­tique courante, au moins pour les améri­cains qui doivent avoir des serveurs sur les deux côtes, synchro­ni­sés entre eux.

Fonc­tion­nel­le­ment

J’ai des visi­teurs qui vont accé­der en lecture, en écri­ture ou en modi­fi­ca­tion à des données. Ces visi­teurs peuvent être répar­tis géogra­phique­ment et j’ai­me­rai que dans la mesure du possible, ils puissent accé­der à leurs données rapi­de­ment. Par rapi­de­ment j’en­tends « sans avoir à payer 100 à 200 ms de latence pour joindre un serveur de base de données sur une autre côte ou sur un autre conti­nent ».

Là où j’ai de la chance, c’est qu’une même données ne sera crée, modi­fiée ou lue que par un seul utili­sa­teur (ou presque). Cet utili­sa­teur sera donc le plus souvent au même endroit, donc je peux répar­tir mes données en consi­dé­rant qu’un seul serveur est maître sur chaque données. Dans mon esprit ça veut dire que ce sera rapide (données proches) 90% du temps et lent (serveur maître loin) les 10% du temps restant si l’uti­li­sa­teur navigue géogra­phique­ment. Par contre il faut que lors de la créa­tion d’une donnée, je puisse choi­sir quel serveur sera le maître pour la donnée en ques­tion (pas de répar­ti­tion auto­ma­tique par hachage de clef puisque le maître est choisi en fonc­tion de la proxi­mité géogra­phique).

Histoire de complé­ter : J’ai assez peu de rela­tion­nel dans ces données et j’y accède quasi­ment toujours par leur clef primaire. Je suis prêt à utili­ser du SGBDR type MySQL, du clef/valeur type Redis, ou des inter­mé­diaires type MongoDB (bon, j’ai une préfé­rence pour du Redis, qui serait mon choix sans la contrainte multi-maître).

J’ai des volumes qui vont repré­sen­ter plusieurs Go, entre 5 et 20 on va dire à vue de nez, non vola­tiles (donc j’ex­clue tout système qui ne permet pas de sauve­garde ou qui n’a pas de couche écri­ture disque). La perfor­mance est impor­tance lors des accès, mais je ne vais pas avoir un débit d’écri­ture phéno­mé­nal non plus. Je ne pense pas que ce soit le critère de choix prin­ci­pal.

Enfin, je n’ai pas besoin d’écri­tures synchrones sur plusieurs serveurs. Je suis prêt à avoir une latence d’une ou plusieurs secondes avant de pouvoir accé­der à une nouvelle donnée (ou à une modi­fi­ca­tion) depuis un autre serveur que celui de sa créa­tion.

Tech­nique­ment

Beau­coup de solu­tions ont un mode maître-maître qui ne semble pas conve­nir à mon besoin, où les conflits peuvent être légion : Si un utili­sa­teur fait volon­tai­re­ment une opéra­tion sur une données à partir de plusieurs empla­ce­ments géogra­phique, je risque de ne pas pouvoir tracer ses diffé­rentes opéra­tions mais d’avoir au mieux la trace de la dernière. Sauf erreur de ma part, les bidouillages multi-maîtres MySQL et Post­greSQL entrent dans cette caté­go­rie.

J’ai jeté un oeil à Redis-clus­ter, qui a l’air d’être assez proche de la philo­so­phie que je cherche (chaque donnée a un et un seul maître) mais c’est malheu­reu­se­ment avec une isola­tion complète, c’est à dire qu’au­cun noeud n’a l’en­semble des infor­ma­tions en lecture. J’y vien­drai s’il le faut, mais si je veux un fail-over correct ça veut dire qu’il faut que je double chaque noeud (le maître, puis son esclave en cas de défaillance). Je ne suis pas non plus certain de pouvoir choi­sir le maître à utili­ser lors de l’écri­ture.

Je regarde Riak, CouchDB, RethinkDB, Tyrant, Volde­mort, Dyno­mite et quelques autres mais je manque cruel­le­ment de retours d’ex­pé­rience et d’in­for­ma­tions pour faire un choix éclairé, si tant est que l’un de ceux là puisse corres­pondre.

J’ai aussi en tête de faire quelque chose à la main avec une logique appli­ca­tive par dessus le connec­teur Redis, pour qu’il se connecte au bon serveur en fonc­tion du premier carac­tère de la clef, mais j’ai­me­rai fran­che­ment éviter les bidouilles manuelle pour quelque chose qui doit certai­ne­ment avoir une solu­tion sur étagère.

Dis, lecteur, as tu des liens, des retours d’ex­pé­rience, des infor­ma­tions, des commen­taires ?

 


Publié

dans

,

par

Étiquettes :

Commentaires

11 réponses à “Bases de données en master – master”

  1. Avatar de Ori Pekelman

    Salut,

    Je ne comprends pas trop. Si j’ai bien compris tu veux des sessions sticky vers une base de données sur deux, et puis tu veux avoir de la replication lazy (dont l’utilité ne m’est pas très claire, pourquoi l’utilisateur ne restera pas sur son serveur, un tout petit peu distant quand il est en « roaming »)? C’est pour de la haute-dispo? Pas sûr que c’est la bonne solution.

    Donc en gros tu assigne à l’utilisateur la base que tu veux tu le mets dans la session ou même dans un cookie si tu veux, il reste toujours sur sa base et basta. Pas besoin de répliquer. Si jamais tu veux tu peux toujours faire une procédure de migration des comptes entre les deux serveurs. Quand il se loggue tu peux toujours vérifier sur quelle base il est censé aller. A la limité tu peux toujours répliquer cette info.

    Une bonne manière de faire c’est peut-être d’utiliser simplement Postgres avec des schemas per utilisateur. Tu peux alors avoir sur chaque côté geographique deux instances. Un master et un slave. Tu peux même alors répliquer les schémas (en gros chaque noeud devient master pour ses propres utilisateurs et slaves des utilisateurs de l’autre).

    Si tu le fais avec du Ruby il y’a des supers-dupers outils pour ça. Regarde surtout https://github.com/influitive/apartment ça fait ça automatiquement plus ou moins.
    Mais aussi https://github.com/bpot/data_fabric

    Autrement, si ta donnée est non-volatile, elle pèse déjà une vingtaine de Go alors Redis, hmm je suis loin d’être sûr. Pour ce qui est du master/master CouchDB a été construit pour. Ca fait maintenant quelques années que je l’utilise plus trop mais si tu ne veux pas écrire du code du tout…

    1. Avatar de edaspet
      edaspet

      > pourquoi l’utilisateur ne restera pas sur son serveur
      > Quand il se loggue tu peux toujours vérifier sur quelle base il est censé aller.

      Parce que si c’est quasiment toujours le même utilisateur qui demande la donnée, je n’ai pas l’information quand je fais les get/set. Je ne peux donc pas choisir le serveur en fonction de l’utilisateur en cours. Sinon oui, ce serait le plus adéquat (bête sharding, on oublie toute réplication)

      > C’est pour de la haute-dispo?

      Essentiellement mon besoin de base ici c’est de la performance : m’assurer que pour réaliser une opération je n’ai pas besoin de joindre une base de données à l’autre bout du globe, ce qui donnerait une expérience bien pourrie.

      > Autrement, si ta donnée est non-volatile, elle pèse déjà une vingtaine de Go alors Redis, hmm je suis loin d’être sûr

      Je n’ai pas d’expérience sur de gros volumes là dessus (en fait nulle part ailleurs qu’en SGBDR). Je suis preneur d’infos ou de retours si tu en as. Là à chaud je n’ai rien dans les docs qui me dise « pas de grosse donnée stp » et un manque cruel d’info, donc je n’ai rien exclu.
      Tu aurais quoi pour des volumes de l’ordre de 20 Go avec synchro disque ?

    2. Avatar de Pierre Chapuis

      À ce que je comprends de ton problème, c’est plutôt *plusieurs* bases master-slave que du master-master qu’il te faut. Ou disons que tu peux éviter le master-master donc j’aurais tendance à le faire.

      Ce que je ferais, c’est mettre toutes les données d’un utilisateur au même endroit comme le suggère Ori, vu que les utilisateurs sont supposés ne pas bouger. Tu as donc besoin d’une DB qui store les associations utilisateur – lieu. Cette DB est répliquée partout, avec un maitre dans un endroit quelconque (on écrit rarement dedans, en gros uniquement à la création de comptes utilisateur…). Quand un utilisateur se connecte tu résouds l’emplacement de son maitre sur la copie locale de cette DB, et ensuite tu tapes dessus.

      Ensuite, si tu as par exemple 3 DC A, B et C, tu peux mettre un master dans chaque DC (mA, mB, mC) et des slaves pour chacun d’entre eux dans les autres. Tu peux faire ça avec Redis sans problème. Par contre oublie Cluster, il est loin d’être utilisable pour l’instant. C »est juste de la réplication master-slave basique.

      Bon, ce système demande *un peu* de logique applicative, mais je ne vois pas de solution qui va faire ça (la « géolocalisation » du master) out-of-the-box.

      Concernant les 20 Go dans Redis, ça se fait, ça veut juste dire qu’il te faut des instances avec 32 Go de RAM (Redis met tout son dataset en RAM et il lui en faut un peu plus pour persister sur disque à cause du CoW, personnellement je recommande au moins 1/2 du dataset d’overhead, surtout sur EC2 / EBS où les écritures sur disques sont lentes). À toi de voir si tu veux payer ce prix-là.

      Sinon si tu veux vraiment du master-master j’aurais tendance à dire CouchDB. Et comme dit par quelqu’un d’autre l’expert du domaine c’est @benoitc :)

    3. Avatar de Pierre Chapuis

      (Pour être clair, quand je dis « DB » j’entends dans le cas de Redis « instance de Redis », pas les DB que tu choisis avec SELECT.)

    4. Avatar de edaspet
      edaspet

      J’ai dit qu’une même donnée est quasiment toujours modifiée par le même utilisateur, je n’ai pas dit que je savais identifier quel est l’utilisateur concerné. Je ne vois que des demandes d’écriture, anonymes (enfin pas anonymes, mais pas identifiées par l’utilisateur qui fait la modification).

      Du coup non, je ne peux pas faire de sharding par identifiant ou base utilisateur. C’est bien pour ça que je m’oriente vers du maitre-maitre et non du maitre-esclave.

      La seule solution que je vois c’est déterminer moi-même le maître lors de l’écriture, et indiquer l’identifiant de la base maître dans l’identifiant unique de ma donnée (comme ça je sais toujours à quel shard m’adresser) mais ça fait un très bidouille quand même (outre le fait que du coup je n’ai aucune base avec l’ensemble des données, donc le reporting sera plus complexe)

  2. Avatar de Jérôme
    Jérôme

    Hello,

    J’ai du mal à saisir ce que tu veux faire exactement, peut-être est-ce simplement un soucis de formulation (ou moi qui ne suis pas réveillé …). Mais dans le doute, as-tu regardé Elasticsearch dans tes options ?

    Gérer une réplication de 20Gb sur disque n’est pas un soucis, et tu peux sharder 1 (ou N) index(es) comme tu le souhaites. Pour la problématique géographique, tu gère ça avec du routing pour taper dans le bon shard.

    Certes, ElasticSearch, c’est un moteur de recherche, mais tu peux très bien l’utiliser comme base de données simple, sans analyse de champs si tu le souhaite. Si tu reste dans des opérations type GET/SET sans autre complication, ça pourrait être une option intéressante pour toi

    Quelques liens, au cas ou ça t’aide:
    http://www.elasticsearch.org/guide/reference/modules/node/
    http://www.elasticsearch.org/guide/reference/index-modules/allocation/
    http://www.elasticsearch.org/blog/customizing-your-document-routing/

  3. Avatar de Benjamin Dos Santos

    Hello,

    My 2ct :

    Il y a deux ans j’ai monté une infra avec du CouchDB, qui d’ailleurs tourne
    toujours.

    Il me semble que ce que tu souhaite faire est possible avec cette techno
    (ou les dérivés genre CouchBase), voir même avec Riak (jamais testé).

    En vrac :

    * Plusieurs groupes de 2+ noeuds CouchDB en multi-master réparties dans plusieurs
    zones
    * Du load balancing HTTP devant les groupes (CouchDB est RESTful …), avec du
    sticky session au cas ou la replication aurait un léger lag.
    * Du routage basé sur la latence vers les LB (R53, par exemple)
    *Optionnellement du sharding; #BIGDATAS #BUZZWORDZ

    Quelques avantages que j’ai trouvé à Couch (d’un point de vue Ops) :

    * Simple de scale up : snapshot à chaud d’une DB + démarrage de la réplication
    (qui va rattraper son retard). En plus archaïque : rsync/scp des db vers la nouvelle
    machine + démarrage de la réplication pour rattraper le retard.
    * Simple à backup à chaud : snapshot du FS etc …
    * Ça s’industrialise bien …
    * Plusieurs type de réplication : One-Shot, continue …

    Inconvénients :

    * La compaction/Décompaction d’une DB : attention à l’espace disque.
    * La ré-indexation d’une vue peut être « longue »
    * Compacter une DB : attention les I/O

    Si ça t’intéresse, une présentation (scolaire donc « vulgarisé ») est disponible
    ici : -http://bdossantos.github.com/TOM-infrastructure-slides/#29

    Il y a quelques chiffres pour te donner une idée de la volumétrie, le schéma
    de l’infra etc …

    Disponible si tu as des questions.

    1. Avatar de Nicolas Steinmetz

      J’aurais pensé aussi à CouchDB et son système de réplication multi-master en espérant que le cout de réplication soit faible et qu’ainsi tu puisses en fait toujours proposer à ton utilisateur la base de donnée la plus proche, qqsoit le lieu où il soit.

      Néanmoins, je n’ai pas de retour d’XP significatifs sur le sujet ; si tu veux un avis d’un codeur CouchDB, demaine à Benoit Chesneau (@benoitc)

      Pour ce que j’ai pu lire par ailleurs sur CouchDB, je pense que Sebastien a bien résumé les avantages/inconvénients de la solution.

  4. Avatar de Bruno

    Salut,

    ton problème me fait sérieusement penser à Cassandra. C’est, a priori, la BDD qui sait le mieux gérer des masters dans plusieurs datacenters. Je n’y ai pas touché depuis longtemps, mais les échos que j’ai eu sont positifs.

    Sinon, ça doit aussi pouvoir se faire avec Redis en bidouillant un peu de code, ou avec Couchdb (même si je n’aime pas son comportement un peu trop aléatoire parfois).

  5. Avatar de nico
    nico

    J’allais le dire Bruno,

    Cassandra, c’est exactement la réponse à ton problème.

    Je compte l’utiliser sous peu dans un système de production où si ça fonctionne, évoluera de manière horizontal.

    Pour moi, le seul hic, c’est l’aspect sécurité, y’a très peu de configuration nécessaire et ça me semble un peu faible (j’ai pas pu m’y pencher encore)
    Sinon, pour ce qui est rapidité et notion de maitre-maitre, c’est le top.

    C’est un produit développé en Java et maintenu par une entité nommé DataStax (qui fourni Tuto et Infos) sous la coup d’Apache…
    C’est un des projets prioritaire et au rythme des releases, et depuis la v1, il ne manque rien à Cassandra par rapport à un MySQL (car oui, Cassandra peu être interroger en SQL depuis PHP par exemple).

  6. Avatar de edaspet
    edaspet

    Quelques pistes après vos retours et bien d’autres :

    * Du Cassandra, avec la chance que MariaDB sait taper dedans donc le pont avec mes systèmes SQL sera simplifié. J’avoue que j’ai du mal à me décider à me lancer là dedans.

    * Du MySQL avec un sharding « fait main », serveurs totalement indépendants, éventuellement un petit outil en intermédiaire qui sait me dire sur quel serveur est ma donnée en fonction de la clef primaire. Ca demande de la bidouille (aie) et de faire un import à côté en plus pour rapatrier toutes les données quelques part afin de faire les traitements analytiques complets

    * Du MySQL avec du sharding « fait main », et à côté à chaque localisation un esclave en lecture qui profite de la nouvelle fonctionnalité MariaDB pour faire de la réplication multi-source (le slave récupère les données du maitre local mais aussi celles des maitres distants). Il restera que pour les mises à jour des données il sera nécessaire de savoir sur quel serveur taper, et donc d’avoir un système qui me permet d’identifier l’origine des données

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *