Bonjour,
actuellement nous gérons la répartition de charge sur les serveurs MySQL en PHP, avec un preg_match sur la requête pour l'envoyer soit sur le master, soit sur un slave pondéré.
Ca fonctionne bien, et le random sur la pondération répartit la charge équitablement.
Mais quand je dois intervenir sur un serveur, je dois travailler avec les développeurs pour supprimer temporairement un slave, puis l'ajouter petit à petit lorsque j'ai terminé, le temps qu'il charge ses index en mémoire...
J'aimerais gérer cette répartition de A à Z, et que ce soit fait plus élégamment qu'un preg_match + random dans un tableau PHP ... C'est là qu'intervient MySQL Proxy : avec son script rw-splitting.lua il est sensé gérer tout ça.
Mais ce script est loin d'être complet, en plus je constate que la majorité des requêtes de lecture (SELECT) vont sur le master... Sur son site http://forge.mysql.com/wiki/MySQL_Proxy_RW_Splitting Jan précise bien que /Yes, we know that RW-Splitting is not for production use yet, it is a Proof of Concept./
Malgré tout j'aime l'idée, donc je me demandais si je pouvais avoir des retours d'expériences sur MySQL Proxy et particulièrement sur ce script lua !
Et si non, si vous connaissiez un système qui analyse les requêtes et load-balance sur les slaves et le master de manière automatique. Il faudrait que les développeurs n'aient qu'une IP par database et ce système se charge du reste.
Salut,
J'ai le même mode opératoire que toi actuellement, la répartition se fait au niveau code. J'avais également regardé mysql proxy, qui effectivement, me semblait une bonne idée, malheureusement le split r/w ne fonctionne pas bien. De ce que j'avais pu voir et de ce qu'on m'en avait dit à l'époque, il faudrait revoir / ré-écrire ce fameux script.
Si qqun l'a déjà fait, je suis preneur, sinon on pourra regarder ensemble !
Le 25 août 2011 11:54, Gregory Duchatelet greg-frsag@duchatelet.net a écrit :
Bonjour,
actuellement nous gérons la répartition de charge sur les serveurs MySQL en PHP, avec un preg_match sur la requête pour l'envoyer soit sur le master, soit sur un slave pondéré.
Ca fonctionne bien, et le random sur la pondération répartit la charge équitablement.
Mais quand je dois intervenir sur un serveur, je dois travailler avec les développeurs pour supprimer temporairement un slave, puis l'ajouter petit à petit lorsque j'ai terminé, le temps qu'il charge ses index en mémoire...
J'aimerais gérer cette répartition de A à Z, et que ce soit fait plus élégamment qu'un preg_match + random dans un tableau PHP ... C'est là qu'intervient MySQL Proxy : avec son script rw-splitting.lua il est sensé gérer tout ça.
Mais ce script est loin d'être complet, en plus je constate que la majorité des requêtes de lecture (SELECT) vont sur le master... Sur son site http://forge.mysql.com/wiki/MySQL_Proxy_RW_Splitting Jan précise bien que *Yes, we know that RW-Splitting is not for production use yet, it is a Proof of Concept.*
Malgré tout j'aime l'idée, donc je me demandais si je pouvais avoir des retours d'expériences sur MySQL Proxy et particulièrement sur ce script lua !
Et si non, si vous connaissiez un système qui analyse les requêtes et load-balance sur les slaves et le master de manière automatique. Il faudrait que les développeurs n'aient qu'une IP par database et ce système se charge du reste.
-- Greg
Liste de diffusion du FRsAG http://www.frsag.org/
Bonjour,
malheureusement, pour répartir des requêtes en R/W, je ne pense pas qu'il existe de solution autre que théorique sans passer par un cluster mysql.
JeFF
On Thu, 2011-08-25 at 11:54 +0200, Gregory Duchatelet wrote:
Bonjour,
actuellement nous gérons la répartition de charge sur les serveurs MySQL en PHP, avec un preg_match sur la requête pour l'envoyer soit sur le master, soit sur un slave pondéré.
Ca fonctionne bien, et le random sur la pondération répartit la charge équitablement.
Mais quand je dois intervenir sur un serveur, je dois travailler avec les développeurs pour supprimer temporairement un slave, puis l'ajouter petit à petit lorsque j'ai terminé, le temps qu'il charge ses index en mémoire...
J'aimerais gérer cette répartition de A à Z, et que ce soit fait plus élégamment qu'un preg_match + random dans un tableau PHP ... C'est là qu'intervient MySQL Proxy : avec son script rw-splitting.lua il est sensé gérer tout ça.
Mais ce script est loin d'être complet, en plus je constate que la majorité des requêtes de lecture (SELECT) vont sur le master... Sur son site http://forge.mysql.com/wiki/MySQL_Proxy_RW_Splitting Jan précise bien que Yes, we know that RW-Splitting is not for production use yet, it is a Proof of Concept.
Malgré tout j'aime l'idée, donc je me demandais si je pouvais avoir des retours d'expériences sur MySQL Proxy et particulièrement sur ce script lua !
Et si non, si vous connaissiez un système qui analyse les requêtes et load-balance sur les slaves et le master de manière automatique. Il faudrait que les développeurs n'aient qu'une IP par database et ce système se charge du reste. -- Greg _______________________________________________ Liste de diffusion du FRsAG http://www.frsag.org/
Salut Grégory,
Clairement l'idéal c'est de le gérer au niveau du code, l'applicatif est mieux placé pour savoir si il fait des modifications suivi d'un read (qui devrait être que sur le master dans ce cas là) par ex.
Mysql proxy permet quand même de palier les applicatifs non prévus pour mais effectivement le script rw split n'est pas parfait. Néanmoins il s'utilise en production, j'ai vu pas mal de personne l'utiliser que ca soit sur des petites structures ou des plus grosses, du coup je le met en place aussi lorsqu'un client a du code qui ne gère pas le split de son côté.
A mon sens voilà les deux solutions qui se présentent à toi dans l'ordre de simplicité et temps passé :
- améliorer ton mécanisme actuel en mettant la liste des serveurs et leur poids dans un fichier de configuration. Normalement tes fichiers de configurations sont propres à chaque environnement (prod / preprod / dev) et c'est uniquement les sys adm qui y ont accès, les fichiers ne devraient pas se trouver dans le repository. Ainsi pour effectuer une maintenance tu n'as qu'à changer le poids et le mettre null ou une variable off au choix. Pour le remettre en activité, il suffirait d'un poids faible que tu changes au fur et à mesure. C'est à mon sens le plus simple.
- améliorer le rw split ou en écrire un autre. Je n'ai pas eu l'occasion et le temps de me pencher sur ce point vu que les requêtes en lecture qui passent sur le master n'étaient pas gênantes pour les différentes plateformes que j'ai rencontré et que il y a avait pas mal de lecture déléguée aux slaves. Après à voir le temps nécessaire pour appréhender les mécanismes des scripts lua disponibles et le langage lua.
A bientôt
Pierre-Henry Muller
Le 25/08/11 11:54, Gregory Duchatelet a écrit :
Bonjour,
actuellement nous gérons la répartition de charge sur les serveurs MySQL en PHP, avec un preg_match sur la requête pour l'envoyer soit sur le master, soit sur un slave pondéré.
Ca fonctionne bien, et le random sur la pondération répartit la charge équitablement.
Mais quand je dois intervenir sur un serveur, je dois travailler avec les développeurs pour supprimer temporairement un slave, puis l'ajouter petit à petit lorsque j'ai terminé, le temps qu'il charge ses index en mémoire...
J'aimerais gérer cette répartition de A à Z, et que ce soit fait plus élégamment qu'un preg_match + random dans un tableau PHP ... C'est là qu'intervient MySQL Proxy : avec son script rw-splitting.lua il est sensé gérer tout ça.
Mais ce script est loin d'être complet, en plus je constate que la majorité des requêtes de lecture (SELECT) vont sur le master... Sur son site http://forge.mysql.com/wiki/MySQL_Proxy_RW_Splitting Jan précise bien que /Yes, we know that RW-Splitting is not for production use yet, it is a Proof of Concept./
Malgré tout j'aime l'idée, donc je me demandais si je pouvais avoir des retours d'expériences sur MySQL Proxy et particulièrement sur ce script lua !
Et si non, si vous connaissiez un système qui analyse les requêtes et load-balance sur les slaves et le master de manière automatique. Il faudrait que les développeurs n'aient qu'une IP par database et ce système se charge du reste. -- Greg
Liste de diffusion du FRsAG http://www.frsag.org/
Le 25/08/2011 16:53, Wallace a écrit :
Salut Grégory,
Salut,
- améliorer ton mécanisme actuel en mettant la liste des serveurs et
leur poids dans un fichier de configuration. Normalement tes fichiers de configurations sont propres à chaque environnement (prod / preprod / dev) et c'est uniquement les sys adm qui y ont accès, les fichiers ne devraient pas se trouver dans le repository. Ainsi pour effectuer une maintenance tu n'as qu'à changer le poids et le mettre null ou une variable off au choix. Pour le remettre en activité, il suffirait d'un poids faible que tu changes au fur et à mesure. C'est à mon sens le plus simple.
A vrai dire je suis déjà dans ce cas là, sauf que par simplicité les dev ont aussi accès aux fichiers de config. Mais n'y touche pas. Ce qui m'intéresse c'est l'étape suivante :
- améliorer le rw split ou en écrire un autre. Je n'ai pas eu
l'occasion et le temps de me pencher sur ce point vu que les requêtes en lecture qui passent sur le master n'étaient pas gênantes pour les différentes plateformes que j'ai rencontré et que il y a avait pas mal de lecture déléguée aux slaves. Après à voir le temps nécessaire pour appréhender les mécanismes des scripts lua disponibles et le langage lua.
Va falloir que je me mette au LUA ! :) Si tu as un script qui marche, ou une version modifié de celui fournit avec MySQL Proxy, je suis preneur !
Greg
Le 25/08/11 16:58, Gregory Duchatelet a écrit :
Va falloir que je me mette au LUA ! :) Si tu as un script qui marche, ou une version modifié de celui fournit avec MySQL Proxy, je suis preneur !
Je n'ai utilisé que le script livré dans les docs de mysql proxy, pas eu besoin d'aller plus loin pour le moment mais tes recherches m'intéressent pour comprendre ce qui cloche dans son script.
Je reste quand même persuadé que tu auras de meilleurs résultats avec la première idée. Seul l'appli sait si elle a besoin de faire un read juste après un update et c'est clairement le problème du split des requêtes. Dans mon code de mon projet quand j'execute une requête sql la fonction d'appel a une variable pour forcer à être sur le master. Si elle est présente alors peut importe si la requête ne comporte qu'un select elle sera quand même passer sur le master et pas sur les slaves. Ca le mysql proxy ne le saura jamais. Quand les devs jouent à ce genre de mise à jour puis get tu peux pas trop te permettre d'attendre 1 ou plusieurs secondes que ca se synchronise.
Le 25/08/2011 17:56, Wallace a écrit :
Le 25/08/11 16:58, Gregory Duchatelet a écrit :
Va falloir que je me mette au LUA ! :) Si tu as un script qui marche, ou une version modifié de celui fournit avec MySQL Proxy, je suis preneur !
Je n'ai utilisé que le script livré dans les docs de mysql proxy, pas eu besoin d'aller plus loin pour le moment mais tes recherches m'intéressent pour comprendre ce qui cloche dans son script.
Je reste quand même persuadé que tu auras de meilleurs résultats avec la première idée. Seul l'appli sait si elle a besoin de faire un read juste après un update et c'est clairement le problème du split des requêtes.
Notre appli utilise cette regexp pour savoir s'il faut taper sur un slave ou pas :
preg_match("/^([\r\n\t ]+)?(SELECT|USE|SET|CALL (stats)?|DESCRIBE|(CREATE|DROP) TEMPORARY TABLE|()/i", trim($query), $r);
Avec ça l'appli n'a pas besoin de "savoir".
Dans mon code de mon projet quand j'execute une requête sql la fonction d'appel a une variable pour forcer à être sur le master. Si elle est présente alors peut importe si la requête ne comporte qu'un select elle sera quand même passer sur le master et pas sur les slaves. Ca le mysql proxy ne le saura jamais. Quand les devs jouent à ce genre de mise à jour puis get tu peux pas trop te permettre d'attendre 1 ou plusieurs secondes que ca se synchronise.
Si, dans le script LUA on peut faire ce qu'on veut ! Imagines, tu peux faire un simple SET forcemaster=1 Et dans le script LUA, catcher ce SET, stocker dans une variable un peu comme la variable is_in_transaction de ce même script, et voilà :)
Pour info, le script LUA en question est visible ici : http://paste.frsag.net/TAWVp
Un R/W splitting doit prendre en compte enormement de parametres. Comment traiter un last insert id ? Comment traiter une transaction ? De plus, MySQL-proxy a un defaut dans la gestion des sessions. Je ne sais pas s'il a été corrigé mais cela avait provoqué un gros NOGO sur un gros projet pour nous.
En gros : un user U1 qui n'a le droit que d'acceder au schema A se connecte au proxy, le proxy ouvre une sessions avec l'instance et transmet l'auth du user U1 un user U2 qui n'a le droit que d'acceder au schema B se connecte au proxy, le proxy peut reutiliser la session ouverte precedemment pour U1 sauf que la requete va etre rejetée car l'auth a deja été faite par U1 et que celui-ci n'a pas acces au schema B.
Deuxieme probleme. Un java hibernate se connecte et créé un pool de connexions vers mysql-proxy, mysql-proxy créé des connections vers l'instance. pour une raison ou une autre les connexions entre mysql-proxy et l'instance sont coupées. Hibernate n'est pas informée et donc ses requetes sont mortes.
Ce sont deux cas rencontrés il y a plus d'un an et depuis nous avons abandonné l'idée d'utiliser Mysql-proxy. Nos clients qui font de l'usage intensif (plus de 5000hits/s) utilisent un LB au niveau du code pour determiner s'ils attaquent le master ou le slave et les slaves sont derriere un LB software genre lvs.
My 2 cents.
Le 26 août 2011 15:15, Gregory Duchatelet greg-frsag@duchatelet.net a écrit :
Le 25/08/2011 17:56, Wallace a écrit :
Le 25/08/11 16:58, Gregory Duchatelet a écrit :
Va falloir que je me mette au LUA ! :) Si tu as un script qui marche, ou une version modifié de celui fournit avec MySQL Proxy, je suis preneur !
Je n'ai utilisé que le script livré dans les docs de mysql proxy, pas eu besoin d'aller plus loin pour le moment mais tes recherches m'intéressent pour comprendre ce qui cloche dans son script.
Je reste quand même persuadé que tu auras de meilleurs résultats avec la première idée. Seul l'appli sait si elle a besoin de faire un read juste après un update et c'est clairement le problème du split des requêtes.
Notre appli utilise cette regexp pour savoir s'il faut taper sur un slave ou pas :
preg_match("/^([\r\n\t ]+)?(SELECT|USE|SET|CALL (stats)?|DESCRIBE|(CREATE|DROP) TEMPORARY TABLE|()/i", trim($query), $r);
Avec ça l'appli n'a pas besoin de "savoir".
Dans mon code de mon projet quand j'execute une requête sql la fonction d'appel a une variable pour forcer à être sur le master. Si elle est présente alors peut importe si la requête ne comporte qu'un select elle sera quand même passer sur le master et pas sur les slaves. Ca le mysql proxy ne le saura jamais. Quand les devs jouent à ce genre de mise à jour puis get tu peux pas trop te permettre d'attendre 1 ou plusieurs secondes que ca se synchronise.
Si, dans le script LUA on peut faire ce qu'on veut ! Imagines, tu peux faire un simple SET forcemaster=1 Et dans le script LUA, catcher ce SET, stocker dans une variable un peu comme la variable is_in_transaction de ce même script, et voilà :)
Pour info, le script LUA en question est visible ici : http://paste.frsag.net/TAWVp
-- Greg
Liste de diffusion du FRsAG http://www.frsag.org/
Intéressantes ces remarques, est ce que tu te souviens de la version de mysql proxy testée?
Je repose une autre question, quand un client veut faire un site forte charge à partir d'un CMS ou moteur de blog du marché et que ces derniers n'ont pas d'intelligence dans la répartition de charge quel type de solution autre que mysql proxy vous utiliseriez? On devrait pouvoir développer une surcharge de la classe sql pour faire le split mais les clients n'ont bizarrement jamais de budget pour cela.
Le 26/08/11 16:54, Sébastien FOUTREL a écrit :
Un R/W splitting doit prendre en compte enormement de parametres. Comment traiter un last insert id ? Comment traiter une transaction ? De plus, MySQL-proxy a un defaut dans la gestion des sessions. Je ne sais pas s'il a été corrigé mais cela avait provoqué un gros NOGO sur un gros projet pour nous.
En gros : un user U1 qui n'a le droit que d'acceder au schema A se connecte au proxy, le proxy ouvre une sessions avec l'instance et transmet l'auth du user U1 un user U2 qui n'a le droit que d'acceder au schema B se connecte au proxy, le proxy peut reutiliser la session ouverte precedemment pour U1 sauf que la requete va etre rejetée car l'auth a deja été faite par U1 et que celui-ci n'a pas acces au schema B.
Deuxieme probleme. Un java hibernate se connecte et créé un pool de connexions vers mysql-proxy, mysql-proxy créé des connections vers l'instance. pour une raison ou une autre les connexions entre mysql-proxy et l'instance sont coupées. Hibernate n'est pas informée et donc ses requetes sont mortes.
Ce sont deux cas rencontrés il y a plus d'un an et depuis nous avons abandonné l'idée d'utiliser Mysql-proxy. Nos clients qui font de l'usage intensif (plus de 5000hits/s) utilisent un LB au niveau du code pour determiner s'ils attaquent le master ou le slave et les slaves sont derriere un LB software genre lvs.
My 2 cents.
Le 26 août 2011 15:15, Gregory Duchatelet greg-frsag@duchatelet.net a écrit :
Le 25/08/2011 17:56, Wallace a écrit :
Le 25/08/11 16:58, Gregory Duchatelet a écrit :
Va falloir que je me mette au LUA ! :) Si tu as un script qui marche, ou une version modifié de celui fournit avec MySQL Proxy, je suis preneur !
Je n'ai utilisé que le script livré dans les docs de mysql proxy, pas eu besoin d'aller plus loin pour le moment mais tes recherches m'intéressent pour comprendre ce qui cloche dans son script.
Je reste quand même persuadé que tu auras de meilleurs résultats avec la première idée. Seul l'appli sait si elle a besoin de faire un read juste après un update et c'est clairement le problème du split des requêtes.
Notre appli utilise cette regexp pour savoir s'il faut taper sur un slave ou pas :
preg_match("/^([\r\n\t ]+)?(SELECT|USE|SET|CALL (stats)?|DESCRIBE|(CREATE|DROP) TEMPORARY TABLE|()/i", trim($query), $r);
Avec ça l'appli n'a pas besoin de "savoir".
Dans mon code de mon projet quand j'execute une requête sql la fonction d'appel a une variable pour forcer à être sur le master. Si elle est présente alors peut importe si la requête ne comporte qu'un select elle sera quand même passer sur le master et pas sur les slaves. Ca le mysql proxy ne le saura jamais. Quand les devs jouent à ce genre de mise à jour puis get tu peux pas trop te permettre d'attendre 1 ou plusieurs secondes que ca se synchronise.
Si, dans le script LUA on peut faire ce qu'on veut ! Imagines, tu peux faire un simple SET forcemaster=1 Et dans le script LUA, catcher ce SET, stocker dans une variable un peu comme la variable is_in_transaction de ce même script, et voilà :)
Pour info, le script LUA en question est visible ici : http://paste.frsag.net/TAWVp
-- Greg
Liste de diffusion du FRsAG http://www.frsag.org/
Liste de diffusion du FRsAG http://www.frsag.org/
Je repose une autre question, quand un client veut faire un site forte charge à partir d'un CMS ou moteur de blog du marché et que ces derniers n'ont pas d'intelligence dans la répartition de charge quel type de solution autre que mysql proxy vous utiliseriez?
T'as un exemple concret ? Assez rapidement, les caches (mysql et http) font le plus gros du boulot pour soulager les requêtes de lecture, surtout pour du CMS/blog "bateau". S'il devient nécessaire d'optimiser le cache et qu'il est envisageable de taper dans le code, memcached est une solution qui a fait ses preuves.
Le 27/08/11 12:53, Benjamin Billon a écrit :
Je repose une autre question, quand un client veut faire un site forte charge à partir d'un CMS ou moteur de blog du marché et que ces derniers n'ont pas d'intelligence dans la répartition de charge quel type de solution autre que mysql proxy vous utiliseriez?
T'as un exemple concret ? Assez rapidement, les caches (mysql et http) font le plus gros du boulot pour soulager les requêtes de lecture, surtout pour du CMS/blog "bateau". S'il devient nécessaire d'optimiser le cache et qu'il est envisageable de taper dans le code, memcached est une solution qui a fait ses preuves.
Des exemples concrets j'en ai mais je ne pourrais pas les citer.
Il faut imaginer un site fait sous Drupal ou Wordpress par ex, 50 contributeurs pratiquement en simultanés tous les jours donc les caches seront souvent vidés, des stats élevées on est dans une fourchette entre 1 et 2 millions de pages vues / jour. Le serveur sql actuel est une super grosse machine bien gavée mais pas du tout redondée et elle souffre vraiment malgrès un raid 10 de ssd, des cpus, de la ram à foison. Pour savoir si les caches suffiraient sans contributions, j'ai demandé une période de plusieurs heures un we sans aucune contribution, le nombre de requête diminue, le serveur respire mais sans plus. En consultation pure on est à ~75% read 25% write. La nouvelle architecture doit répondre à l'ouverture du site dans plusieurs nouvelles langues, public visé prévu x 3 d'ici à 1 an et demi, il faut donc augmenter la capacité de lecture.
la nouvelle archi faite :
- plusieurs front web, apc opcode - plusieurs proxy pour les statics - des srv memcache avec 2 instances memcached pour séparer les sessions et le cache de l'appli - 2 mysql en réplication master/master avec une vip sur l'un pour les requêtes write, l'autre n'est qu'un hot standby - des mysql en slave pour la lecture et un pour les backups
L'application que le client fait développer ne comporte pas de mécanisme pour faire du split des requêtes, les développeurs ont dit que c'était compliqué et que ça couterait cher à développer, du coup c'est au niveau système qu'il faut trouver une solution. Sachant que le serveur le plus costaud ne suffira pas à tenir la charge sql et qu'après une consultation mysql cluster n'est pas adapté à ce type de base et de vue, la réplication est donc la seule possibilité pour augmenter les capacités.
J'ai donc ajouté 2 mysql-proxy HA en rw split en étant conscient du problème potentiel du last insert id par ex, chose que j'ai remonté aux dev et au client mais ça ne les empêche pas de dormir.
Bref dans des cas comme celui là où la logique voudrait que cela soit fait au niveau du code et non au niveau du système il n'y a pas de solutions autre que celle là à mon sens, je suis néanmoins preneur d'autres solutions si ça existe.
On 27/08/2011 14:39, Pierre-Henry Muller wrote:
Le 27/08/11 12:53, Benjamin Billon a écrit :
Je repose une autre question, quand un client veut faire un site forte charge à partir d'un CMS ou moteur de blog du marché et que ces derniers n'ont pas d'intelligence dans la répartition de charge quel type de solution autre que mysql proxy vous utiliseriez?
T'as un exemple concret ? Assez rapidement, les caches (mysql et http) font le plus gros du boulot pour soulager les requêtes de lecture, surtout pour du CMS/blog "bateau". S'il devient nécessaire d'optimiser le cache et qu'il est envisageable de taper dans le code, memcached est une solution qui a fait ses preuves.
Des exemples concrets j'en ai mais je ne pourrais pas les citer.
Il faut imaginer un site fait sous Drupal ou Wordpress par ex, 50 contributeurs pratiquement en simultanés tous les jours donc les caches seront souvent vidés, des stats élevées on est dans une fourchette entre 1 et 2 millions de pages vues / jour. Le serveur sql actuel est une super grosse machine bien gavée mais pas du tout redondée et elle souffre vraiment malgrès un raid 10 de ssd, des cpus, de la ram à foison. Pour savoir si les caches suffiraient sans contributions, j'ai demandé une période de plusieurs heures un we sans aucune contribution, le nombre de requête diminue, le serveur respire mais sans plus. En consultation pure on est à ~75% read 25% write. La nouvelle architecture doit répondre à l'ouverture du site dans plusieurs nouvelles langues, public visé prévu x 3 d'ici à 1 an et demi, il faut donc augmenter la capacité de lecture.
la nouvelle archi faite :
- plusieurs front web, apc opcode
- plusieurs proxy pour les statics
- des srv memcache avec 2 instances memcached pour séparer les sessions
et le cache de l'appli
- 2 mysql en réplication master/master avec une vip sur l'un pour les
requêtes write, l'autre n'est qu'un hot standby
- des mysql en slave pour la lecture et un pour les backups
L'application que le client fait développer ne comporte pas de mécanisme pour faire du split des requêtes, les développeurs ont dit que c'était compliqué et que ça couterait cher à développer, du coup c'est au niveau système qu'il faut trouver une solution. Sachant que le serveur le plus costaud ne suffira pas à tenir la charge sql et qu'après une consultation mysql cluster n'est pas adapté à ce type de base et de vue, la réplication est donc la seule possibilité pour augmenter les capacités.
J'ai donc ajouté 2 mysql-proxy HA en rw split en étant conscient du problème potentiel du last insert id par ex, chose que j'ai remonté aux dev et au client mais ça ne les empêche pas de dormir.
Bref dans des cas comme celui là où la logique voudrait que cela soit fait au niveau du code et non au niveau du système il n'y a pas de solutions autre que celle là à mon sens, je suis néanmoins preneur d'autres solutions si ça existe.
Bonjour,
pour un cas plus ou moins similaire (SPIP et trafic similaire), on a mis en place deux choses : - varnish en front pour réduire très fortement le boulot de SPIP - ajout/modification de nombreux indexes dans la BDD, ceux par défaut n'étant pas adaptés (à l'époque en tous cas) - ajout de quelques vues réduisant le volume de données à analyser
Si ça peut aider...
Quant à Drupal & Wordpress, je ne saurais dire, jamais administré à ce régime.
Olivier
Le 27/08/11 14:55, Olivier Bonvalet a écrit :
Bonjour,
pour un cas plus ou moins similaire (SPIP et trafic similaire), on a mis en place deux choses :
- varnish en front pour réduire très fortement le boulot de SPIP
- ajout/modification de nombreux indexes dans la BDD, ceux par défaut
n'étant pas adaptés (à l'époque en tous cas)
- ajout de quelques vues réduisant le volume de données à analyser
Si ça peut aider...
Quant à Drupal & Wordpress, je ne saurais dire, jamais administré à ce régime.
Olivier
Bonjour,
Le cache html est géré par l'application sur les memcaches mais le nombre de contribution et les commentaires va forcément faire descendre le ratio hit de ces éléments. C'est un élément que je n'ai plus mettre en application ici.
Pour les index, Drupal était en myisam par défaut on l'a passé en innodb, les index semblent bon pas de requêtes lentes ou autre simplement un nombre conséquent. Pour les vues on en a parlé au dev de trouver le top100 des requêtes les plus courantes qu'on pourrait passer avec une vue mais ca ne s'est pas fait.
Sur ton exemple de spip tu avais des parties html en cache sur le varnish, sans ca donnait quoi à cette charge là. C'est pour me faire une idée de ce cms que je connais mal.
On 27/08/2011 15:00, Pierre-Henry Muller wrote:
Le 27/08/11 14:55, Olivier Bonvalet a écrit :
Bonjour,
pour un cas plus ou moins similaire (SPIP et trafic similaire), on a mis en place deux choses :
- varnish en front pour réduire très fortement le boulot de SPIP
- ajout/modification de nombreux indexes dans la BDD, ceux par défaut
n'étant pas adaptés (à l'époque en tous cas)
- ajout de quelques vues réduisant le volume de données à analyser
Si ça peut aider...
Quant à Drupal& Wordpress, je ne saurais dire, jamais administré à ce régime.
Olivier
Bonjour,
Le cache html est géré par l'application sur les memcaches mais le nombre de contribution et les commentaires va forcément faire descendre le ratio hit de ces éléments. C'est un élément que je n'ai plus mettre en application ici.
Pour les index, Drupal était en myisam par défaut on l'a passé en innodb, les index semblent bon pas de requêtes lentes ou autre simplement un nombre conséquent. Pour les vues on en a parlé au dev de trouver le top100 des requêtes les plus courantes qu'on pourrait passer avec une vue mais ca ne s'est pas fait.
Sur ton exemple de spip tu avais des parties html en cache sur le varnish, sans ca donnait quoi à cette charge là. C'est pour me faire une idée de ce cms que je connais mal.
Pour moi l'intérêt n'était pas vraiment de "mettre en cache du html", mais d'éviter très fortement les appels à Apache/PHP. Par contre effectivement, on a pas de commentaires à gérer. Mais tant qu'on ne demande pas du temps réel, un cache d'une minute aide déjà bien.
Actuellement configuré sur 1 minute, ce cache a un ratio moyen de 95% pour 200 req/s (il ne gère pas les images, seulement html/css/js). Les contributeurs de leurs cotés sont identifiés, et sont totalement exclus du cache Varnish.
On 27/08/2011 16:10, Olivier Bonvalet wrote:
On 27/08/2011 15:00, Pierre-Henry Muller wrote:
Le 27/08/11 14:55, Olivier Bonvalet a écrit :
Bonjour,
pour un cas plus ou moins similaire (SPIP et trafic similaire), on a mis en place deux choses :
- varnish en front pour réduire très fortement le boulot de SPIP
- ajout/modification de nombreux indexes dans la BDD, ceux par défaut
n'étant pas adaptés (à l'époque en tous cas)
- ajout de quelques vues réduisant le volume de données à analyser
Si ça peut aider...
Quant à Drupal& Wordpress, je ne saurais dire, jamais administré à ce régime.
Olivier
Bonjour,
Le cache html est géré par l'application sur les memcaches mais le nombre de contribution et les commentaires va forcément faire descendre le ratio hit de ces éléments. C'est un élément que je n'ai plus mettre en application ici.
Pour les index, Drupal était en myisam par défaut on l'a passé en innodb, les index semblent bon pas de requêtes lentes ou autre simplement un nombre conséquent. Pour les vues on en a parlé au dev de trouver le top100 des requêtes les plus courantes qu'on pourrait passer avec une vue mais ca ne s'est pas fait.
Sur ton exemple de spip tu avais des parties html en cache sur le varnish, sans ca donnait quoi à cette charge là. C'est pour me faire une idée de ce cms que je connais mal.
Pour moi l'intérêt n'était pas vraiment de "mettre en cache du html", mais d'éviter très fortement les appels à Apache/PHP. Par contre effectivement, on a pas de commentaires à gérer. Mais tant qu'on ne demande pas du temps réel, un cache d'une minute aide déjà bien.
Actuellement configuré sur 1 minute, ce cache a un ratio moyen de 95% pour 200 req/s (il ne gère pas les images, seulement html/css/js). Les contributeurs de leurs cotés sont identifiés, et sont totalement exclus du cache Varnish.
J'ai failli oublier : pour ma part je ne conseillerais pas SPIP. Entre les accès disque et le code indébuggable (eval()...), ça a vraiment été galère avant d'arriver à quelque chose d'à peut-prêt scalable.
Il parait que ça s'est amélioré coté disque dans les dernières versions, mais le système de cache + le système de sessions interne malmenaient pas mal le filer, ce qui réduit pas mal les possibilités de "clustering". Du coup on a tout remplacé par une énorme VM redondée (Xen/DRBD).
Le 27/08/2011 14:39, Pierre-Henry Muller a écrit :
L'application que le client fait développer ne comporte pas de mécanisme pour faire du split des requêtes, les développeurs ont dit que c'était compliqué et que ça couterait cher à développer, du coup c'est au niveau système qu'il faut trouver une solution. Sachant que le serveur le plus costaud ne suffira pas à tenir la charge sql et qu'après une consultation mysql cluster n'est pas adapté à ce type de base et de vue, la réplication est donc la seule possibilité pour augmenter les capacités.
Salut,
tu peux aussi leur fournir le preg_match qui va bien que j'ai cité précédemment :
preg_match("/^([\r\n\t ]+)?(SELECT|USE|SET|CALL (stats)?|DESCRIBE|(CREATE|DROP) TEMPORARY TABLE|()/i", trim($query), $r);
Sinon pour résumer il n'y a pas de solutions existantes. Si on s'abstrait de la partie auth/sécurité, alors un script LUA qui va bien pourrait bien faire l'affaire. Pour la partie sécurité, c'est quelque chose de couteux en terme de CPU/latence et donc une partie qui saute de plus en plus, la sécurité est gérée en amont. Drizzle par exemple a déplacé cette partie dans un plugin.
Le 27/08/2011 14:39, Pierre-Henry Muller a écrit :
L'application que le client fait développer ne comporte pas de mécanisme pour faire du split des requêtes, les développeurs ont dit que c'était compliqué et que ça couterait cher à développer, du coup c'est au niveau système qu'il faut trouver une solution.
Hello,
La solution côté système parait souvent plus simple et moins coûteuse mais d'expérience elle finira toujours par te coûter bonbon à plus ou moins long terme (tu vas monter du serveur de plus en plus gros, empiler les rustines puis maintenir des rustines de rustines et perdre du temps en maintenance), jusqu'au jour ou patatras, plus rien ne tiendra la route, tu vas devoir tout refaire de zéro: l'application doit aussi être scalable à son niveau.
Bien entendu, les applis ne sont pas souvent pensées scalabilité (cache, sharding ou au moins ventilation lecture/écriture SQL sur deux connexions différentes), mais il est souvent possible de rajouter tout ça de façon itérative, quitte à patcher au fur et à mesure l'appli: tu fournis une seconde ip virtuelle portée par un keepalived/haproxy/etc pour se connecter à des slaves répliqués, et tu demandes au(x) dev de basculer les requêtes les plus consommatrices (et pas dépendantes de l'éventuel lag de répli) dessus, puis ça tient un peu plus longtemps, et tu réidentifies des requêtes à passer sur la répli, et ainsi de suite.
Ca marche aussi avec la mise en place du cache applicatif (memcached par exemple), et comme suggéré auparavant tu peux également monter un reverse proxy cache (nginx, varnish ou autre) en amont sur des requêtes qui n'ont pas besoin de trop de fraicheur, le but étant de ne pas envoyer des requêtes inutiles sur ton serveur d'appli et ta DB. Tu peux même commencer par le reverse proxy de façon totalitaire (genre si pas de cookie qui dit que le type est logué alors page sortie du cache) si l'appli est vraiment impossible à patcher et qu'il te faut une amélioration de perfs pour hier.
Bon courage,
Salut,
Entièrement d'accord avec toutes ces techniques, heureusement j'ai des clients qui comprennent les enjeux du côté applicatif et font souvent tout ce qu'il faut pour que l'architecture reste simple pour mieux marcher. Mais voilà quand on est fasse à des mamouths (nom que je donne aux grosses entreprises / administrations où il faut 5 réunions espacées de 1 à 2 semaines, autant de rapports plein de blabla et de schéma pour faire la moindre action) et qu'ils prennent la décision de ne pas toucher au code parce que l'entreprise qui fait le développement a dit que c'était compliqué, il faut bien trouver une solution sinon on dit que c'est toi qui n'est pas bon ... Bref éternel débat mais on est bien tous d'accord sur le fait que la bonne solution à l'heure actuelle est côté code sauf que Grégory va nous sortir un nouveau script lua qui va super bien faire son boulot.
Allé Greg un peu de pression au passage :P
Le 30/08/11 00:35, Damien Claisse a écrit :
Hello,
La solution côté système parait souvent plus simple et moins coûteuse mais d'expérience elle finira toujours par te coûter bonbon à plus ou moins long terme (tu vas monter du serveur de plus en plus gros, empiler les rustines puis maintenir des rustines de rustines et perdre du temps en maintenance), jusqu'au jour ou patatras, plus rien ne tiendra la route, tu vas devoir tout refaire de zéro: l'application doit aussi être scalable à son niveau.
Bien entendu, les applis ne sont pas souvent pensées scalabilité (cache, sharding ou au moins ventilation lecture/écriture SQL sur deux connexions différentes), mais il est souvent possible de rajouter tout ça de façon itérative, quitte à patcher au fur et à mesure l'appli: tu fournis une seconde ip virtuelle portée par un keepalived/haproxy/etc pour se connecter à des slaves répliqués, et tu demandes au(x) dev de basculer les requêtes les plus consommatrices (et pas dépendantes de l'éventuel lag de répli) dessus, puis ça tient un peu plus longtemps, et tu réidentifies des requêtes à passer sur la répli, et ainsi de suite.
Ca marche aussi avec la mise en place du cache applicatif (memcached par exemple), et comme suggéré auparavant tu peux également monter un reverse proxy cache (nginx, varnish ou autre) en amont sur des requêtes qui n'ont pas besoin de trop de fraicheur, le but étant de ne pas envoyer des requêtes inutiles sur ton serveur d'appli et ta DB. Tu peux même commencer par le reverse proxy de façon totalitaire (genre si pas de cookie qui dit que le type est logué alors page sortie du cache) si l'appli est vraiment impossible à patcher et qu'il te faut une amélioration de perfs pour hier.
Bon courage,
Comme je l ai deja dit, MySQL-Proxy n'est pas une solution pour ce cas, le probleme n est pas au niveau du LUA (il peux tenter de parcourir les backend pour le changer, il se fera virer par le logiciel).
Regardez plutot du cote de sqlrelay pour cela.
On 30/08/2011 10:47, Pierre-Henry Muller wrote:
Salut,
Entièrement d'accord avec toutes ces techniques, heureusement j'ai des clients qui comprennent les enjeux du côté applicatif et font souvent tout ce qu'il faut pour que l'architecture reste simple pour mieux marcher. Mais voilà quand on est fasse à des mamouths (nom que je donne aux grosses entreprises / administrations où il faut 5 réunions espacées de 1 à 2 semaines, autant de rapports plein de blabla et de schéma pour faire la moindre action) et qu'ils prennent la décision de ne pas toucher au code parce que l'entreprise qui fait le développement a dit que c'était compliqué, il faut bien trouver une solution sinon on dit que c'est toi qui n'est pas bon ... Bref éternel débat mais on est bien tous d'accord sur le fait que la bonne solution à l'heure actuelle est côté code sauf que Grégory va nous sortir un nouveau script lua qui va super bien faire son boulot.
Allé Greg un peu de pression au passage :P
Le 30/08/11 00:35, Damien Claisse a écrit :
Hello,
La solution côté système parait souvent plus simple et moins coûteuse mais d'expérience elle finira toujours par te coûter bonbon à plus ou moins long terme (tu vas monter du serveur de plus en plus gros, empiler les rustines puis maintenir des rustines de rustines et perdre du temps en maintenance), jusqu'au jour ou patatras, plus rien ne tiendra la route, tu vas devoir tout refaire de zéro: l'application doit aussi être scalable à son niveau.
Bien entendu, les applis ne sont pas souvent pensées scalabilité (cache, sharding ou au moins ventilation lecture/écriture SQL sur deux connexions différentes), mais il est souvent possible de rajouter tout ça de façon itérative, quitte à patcher au fur et à mesure l'appli: tu fournis une seconde ip virtuelle portée par un keepalived/haproxy/etc pour se connecter à des slaves répliqués, et tu demandes au(x) dev de basculer les requêtes les plus consommatrices (et pas dépendantes de l'éventuel lag de répli) dessus, puis ça tient un peu plus longtemps, et tu réidentifies des requêtes à passer sur la répli, et ainsi de suite.
Ca marche aussi avec la mise en place du cache applicatif (memcached par exemple), et comme suggéré auparavant tu peux également monter un reverse proxy cache (nginx, varnish ou autre) en amont sur des requêtes qui n'ont pas besoin de trop de fraicheur, le but étant de ne pas envoyer des requêtes inutiles sur ton serveur d'appli et ta DB. Tu peux même commencer par le reverse proxy de façon totalitaire (genre si pas de cookie qui dit que le type est logué alors page sortie du cache) si l'appli est vraiment impossible à patcher et qu'il te faut une amélioration de perfs pour hier.
Bon courage,
Liste de diffusion du FRsAG http://www.frsag.org/
Bonjour, mes tests sur MySQL-proxy avaient eux aussi reveles de gros problemes. Notamment le R/W qui ne fonctionne vraiment pas tres bien, il suffit de lire le code pour comprendre pourquoi...
Pour chaque connexion au proxy, le proxy va decider d un serveur mysql a utiliser, alors que vous n avez pas encore effectue la moindre requete ( du moins c etait comme ca il y a un an et demi, et on ne pouvai pas forcer un changement de serveur via LUA, question de securite ). C est donc un probleme de design.
Il existe un logiciel bien mieux pense pour ce genre de cas, qui s appelle sqlrelay. sqlrelay se connecte d entree a tous les serveurs, avec un pool de connexion, et lorsque vous effectuez des requetes, il va decider sur quel serveur cela doit aller, au lieu de vous affecter un serveur a la connexion.
Par contre sqlrelay ne semble plus maintenu, les erreurs sont mal gerees ... la ML tres peu locace. Autant pour mes tests ca a tres bien fonctionne, autant 1 an apres quand on a voulu vraiment le tester a fond pour eventuellement le mettre en prod, on a eu des plantages des demons sans la moindre explication, ni la moindre erreur dans les logs, et tu te retrouves vite comme un con =)
On 26/08/2011 16:54, Sébastien FOUTREL wrote:
Un R/W splitting doit prendre en compte enormement de parametres. Comment traiter un last insert id ? Comment traiter une transaction ? De plus, MySQL-proxy a un defaut dans la gestion des sessions. Je ne sais pas s'il a été corrigé mais cela avait provoqué un gros NOGO sur un gros projet pour nous.
En gros : un user U1 qui n'a le droit que d'acceder au schema A se connecte au proxy, le proxy ouvre une sessions avec l'instance et transmet l'auth du user U1 un user U2 qui n'a le droit que d'acceder au schema B se connecte au proxy, le proxy peut reutiliser la session ouverte precedemment pour U1 sauf que la requete va etre rejetée car l'auth a deja été faite par U1 et que celui-ci n'a pas acces au schema B.
Deuxieme probleme. Un java hibernate se connecte et créé un pool de connexions vers mysql-proxy, mysql-proxy créé des connections vers l'instance. pour une raison ou une autre les connexions entre mysql-proxy et l'instance sont coupées. Hibernate n'est pas informée et donc ses requetes sont mortes.
Ce sont deux cas rencontrés il y a plus d'un an et depuis nous avons abandonné l'idée d'utiliser Mysql-proxy. Nos clients qui font de l'usage intensif (plus de 5000hits/s) utilisent un LB au niveau du code pour determiner s'ils attaquent le master ou le slave et les slaves sont derriere un LB software genre lvs.
My 2 cents.