MySQL en Cluster Activo/Activo

Guía para impacientes:Tenemos dos máquinas virtuales mysql1 y mysql2

1. Valida la versión de MySQL, yo lo he probado con una MySQL 5.5 en Ubuntu 12.10 y se instala asi:
user@mysql1$sudo apt-get install mysql-server mysql-client
user@mysql2$sudo apt-get install mysql-server mysql-client
2. Crea los usuarios de replicación y test en las dos maquinas:
user@mysql1$mysql -uroot -p
mysql>use mysql;
mysql>GRANT REPLICATION SLAVE ON *.* TO 'replicante1'@'%' IDENTIFIED BY 'rep1';
mysql>GRANT ALL PRIVILEGES ON replicata.* TO 'test'@'%' IDENTIFIED BY 'test';
mysql>FLUSH PRIVILEGES;
mysql>CREATE DATABASE replicata;

user@mysql2$mysql -uroot -p
mysql>use mysql;
mysql>GRANT REPLICATION SLAVE ON *.* TO 'replicante2'@'%' IDENTIFIED BY 'rep2';
mysql>GRANT ALL PRIVILEGES ON replicata.* TO 'test'@'%' IDENTIFIED BY 'test'; 
mysql>FLUSH PRIVILEGES;
mysql>CREATE DATABASE replicata;
3. Modifica el fichero my.ini para que permita la replicación:
user@mysql1$sudo vim /etc/mysql/my.cnf
[mysqld]
...
server-id=1
replicate-same-server-id=0
auto-increment-increment=2
auto-increment-offset=1
replicate-do-db=replicata
log-bin = /var/lib/mysql/mysql-bin.log
binlog-do-db = replicata
relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index
expire_logs_days = 10
max_binlog_size = 200M
...
user@mysql2$sudo vim /etc/mysql/my.cnf
[mysqld]
...
server-id=2
replicate-same-server-id=0
auto-increment-increment=2
auto-increment-offset=2
replicate-do-db=replicata
log-bin = /var/lib/mysql/mysql-bin.log
binlog-do-db = replicata
relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index
expire_logs_days = 10
max_binlog_size = 200M
...
4. Reinicia el servidor:
user@mysql1$sudo service mysql restart
user@mysql2$sudo service mysql restart
5. Modifica el Master, arranca el slave y voila:
user@mysql1$mysql -uroot -p
mysql>change master to master_host=’192.168.1.52’, master_user=’replicante2′, master_password=’rep2′, master_log_file=’mysql-bin.000001′;
mysql>start slave;
user@mysql2$mysql -uroot -p
mysql>change master to master_host=’192.168.1.107’, master_user=’replicante1′, master_password=’rep1′, master_log_file=’mysql-bin.000001′;
mysql>start slave;  
6. Prueba:
user@home$mysql -utest -ptest -hmysql1 replicata
mysql>create table islas(name varchar(20), fecha date);
mysql>insert into islas("menorca", now());
mysql>insert into islas("mallorca", now());
mysql>insert into islas("ibiza", now());
user@home$mysql -utest -ptest -hmysql2 replicata
mysql>select * from islas;
...
3 rows in set
7. Prueba de reentrada en el cluster
Para mysql1 y con el servicio parado y haz más inserts en mysql2.
Levanta mysql1 y comprueba como se actualizan los cambios.
8. Prueba con tu aplicación favorita, aquí va como se escribe un URL con alta disponibilidad desde java:
jdbc:mysql:loadbalance://mysql1:3306,mysql2:3306/replicata?connectTimeout=500&roundRobinLoadBalance=true&loadBalanceStrategy=random

Ah!  que quieres leer más, ;-).

MySQL es una base de datos muy completa y es la primera elección de muchos equipos de desarrollo, porque es una base de datos ligera y te ofrece toda la potencia de una base de datos relacional.
La cosa se complica cuando la quieres llevar a producción porque necesitas alta disponibilidad, más rendimiento y minimizar los tiempos de parada de los servicios. Por eso en muchos entornos de producción Oracle es el rey de las bases de datos.
Pero desde la versión 5.5 el proceso de preparar un Cluster Activo/Activo de MySQL sin almacenamiento compartido se ha simplificado de forma significativa. De hecho es tan sencillo como montar un Cluster Activo/Pasivo, con la ventaja de que tenemos las dos máquinas funcionando, así aprovechamos más la inversión en sistemas, porque no tenemos una de las dos máquinas sin hacer nada y mejoramos sensiblemente el rendimiento total de las aplicaciones porque somos capaces de soportar más transacciones.

Estas pruebas las he hecho con VirtualBox y dos máquinas virtuales (mysql1 IP:192.168.1.107 y mysql2 IP:192.168.1.52), para poder conectar las dos máquinas virtuales y mi máquina host lo he hecho con un adaptador de red puente o Bridged Network en inglés.

Para poder conectar entre las dos bases de datos he borrado del MySQL la variable bind-address del fichero /etc/mysql/my.cnf.

Para que no me diera problemas con usuarios "raros" borre todos los usuarios que crea debian/Ubuntu por defecto y que no tiene nombre:
mysql>delete from user where user = '';

¿Existen otras formas de montar un cluster Activo/Activo en MySQL?
Si, al menos conozco tres más:
- una basada en DRB
- una basada en MySQL Cluster
- una basada en Galera
Estoy pensando en escribir más guías rápidas sobre estas formas de instalarlo, si te interesan deja tu comentario.

¿Se pierden transacciones con este modelo?
Por defecto las transacciones son asíncronas en MySQL, supongo que por temas de rendimiento, pero existe una forma de hacer las transacciones síncronas, de forma que se escriben en el slave antes de hacerlo en el Master y si el slave se ha caido se escribe sólo en el Master, despues de esperar 10 segundos,  de esta forma no se pierden datos por un fallo.
Para configurarlo debes hacer lo siguiente:
user@mysql1$mysql -uroot -p
mysql>use mysql;
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
user@mysql2$mysql -uroot -p
mysql>use mysql;
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
user@mysql1$sudo vim /etc/mysql/my.cnf
[mysqld]
...
rpl_semi_sync_slave_enabled =1
rpl_semi_sync_master_enabled =1
...
user@mysql2$sudo vim /etc/mysql/my.cnf
[mysqld]
...
rpl_semi_sync_slave_enabled =1
rpl_semi_sync_master_enabled =1
...
user@mysql1$sudo service mysql restart
user@mysql2$sudo service mysql restart
user@mysql2$mysql -uroot -p
mysql>use mysql;
mysql>SHOW STATUS LIKE 'Rpl_semi_sync%';
Para probarlo hay varias alternativas, mi opción ha sido ejecutar una clase que insertaba 1.000 líneas, para el slave al llegar a 500 líneas, comprobar como detenía las inserciones a mitad durante 10'', para continuar con las inserciones sin perder la conexión desde el mysql1 vivo. Reiniciar mysql2 y comprobar como nada más reiniciar están disponible las 1.000 líneas. 

¿Donde puedo leer mas?
Para hacer esta entrada me he basado en la fantástica guia de Johan Reymer. Aunque tiene un error en la configuración del fichero my.cnf en la sección de las variables master-* que ahora se configuran con queries.
Este artículo de Gregory Steulet te puede ayudar a entender las transacciones en este modelo. 

Seguro que tienes alguna idea más para probar, alguna idea de porque usar esta u otra opción, el resultado de tu propio benchmark comparativo, algún vídeo de demostración o simplemente me he dejado algún error, si es así, por favor deja un comentario.

Esta entrada se la dedico a un compi que decía que no funciona el cluster activo activo en MySQL.

Comentarios

  1. Me parece un muy buen post. El único comentario es que una alternativa 100% compatible con MySQL es MariaDB (de hecho, son los autores de MySQL que se han ido al lado libre del software). El tema de las replicaciones funciona igualmente bien pues yo lo uso a diario en mi trabajo. Os dejo una url de un artículo que escribí acerca de las diferencias de rendimiento entre MySQL vs MariaDB: http://www.saltos.net/portal/es/detalle/wiki/75/porque-usar-mariadb-en-lugar-de-mysql.htm

    ResponderEliminar
    Respuestas
    1. OK, tomo nota de lo de MariaDB, desde hace tiempo tengo ganas de probarla y por lo que he visto en tu artículo la experiencia es positiva.

      Eliminar
  2. Buen Post Isra, he visto la guía en Barrapunto.

    ResponderEliminar
  3. Buenas tardes

    Una pregunta, con IP flotante como se haria la configuracion

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Como intentan robar las mafias utilizando AutoScout24

Cross Compiling Freeling