|

MySQL Replicación Master-Master

Con la replicación de MySQL podremos tener varios servidores en sincronía, si bien MySQL tiene opciones como MySQL cluster puede que en algunos casos sea demasiado para nuestras necesidades y con una replicación sea suficiente. MySQL no soporta replicación bidireccional, unicamente unidireccional, destinada a tener un maestro y muchos esclavos, pensado para hacer todas las escrituras en el maestro y todas las lecturas en los esclavos y en el maestro.
Esta idea surge a partir de que en aplicaciones de web dinamica normalmente se leen datos más veces de las que se modifica (pero no siempre tiene porque ser así). Aunque MySQL no soporte la replicación bidireccional podemos lograr el mismo efecto haciendo dos unidireccionales, el servidor A sera maestro de B y B esclavo de A, y también B sera maestro de A y A esclavo de B.
Para poder hacer esto modificaremos los autoincreementales para evitar problemas de concurrencia. Empecemos haciendo la replicación del servidor A al servidor B. El escenario:
  • Servidor 1: 192.168.1.11
  • Servidor 2: 192.168.1.12
  • Base de datos (presente en ambos servidores): web
  • Usuario MySQL (lo crearemos para la replicación): replicacion
  • Clave MySQL: BFp7yv1wjqTxg5TLKha0
Un punto importante a tener en cuenta es que la clave que le asignemos al usuario destinado a la replicación no sea mayor de 32 caracteres, en las claves de acceso podemos usar la longitud que deseemos pero la replicación con claves superiores a 32 caracteres pueden darnos fallos de conectividad en la actual versión de MySQL (5.5 cuando se escribió esto). Además, el usuario lo limitaremos a que solo pueda conectarse desde la IP del esclavo.
Muy probablemente el usuario root creado en la instalación del mysql habrá que darlo de alta en la sección usuarios del mysql con el parámetro % para que sea capaz de entrar a configurar el servidor de MySQL desde cualquier IP de red.

En el servidor 1

Para configurar el servidor 1 como maestro editaremos el archivo de configuración /etc/mysql/my.cnf (recordad tener permisos de superusuario para ello). Lo primero que necesitamos es comentar la linea bind-address = 127.0.0.1 porque la conexión entre esclavo y maestro necesita conectar sobre TCP/IP de una maquina a la otra.
#bind-address = 127.0.0.1

Dentro de la cabecera [mysqld] buscamos la linea #server-id = 1 para indicar el server-id del maestro, donde hacer el registro binario con las modificaciones y de qué base de datos. Además modificaremos cuando debe escribir a disco para minimizar las perdidas en caso de fallo del servidor.
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = web
sync_binlog = 1

Después de guardar estos cambios reiniciamos el servidor y entramos a la consola de mysql.
/etc/init.d/mysql restart
mysql -u root -p

Ahora crearemos el usuario para la replicación y obtendremos la información necesaria para indicar al esclavo su maestro, con SHOW MASTER STATUS se nos mostrara en una tabla el archivo de registro binario y la posición, estos datos tenerlos a mano para configurar el esclavo.

Si ya teneis datos en el servidor 1 antes de hacer UNLOCK TABLES sera necesario que con mysqldump exportes los datos con mysqldump –all-databases > dbdump.db y luego uses UNLOCK TABLES aunque tambien esta la opción de usar mysqldump –all-databases –master-data > dbdump.db sin necesidad de usar FLUSH TABLES WITH READ LOCK ni UNLOCK TABLES pero para seguir estas explicaciones sin complicarlas más mejor usa la primera forma. Si tu servidor no tenia datos previamente no hace falta que hagas ninguna exportación ni importación.

GRANT REPLICATION SLAVE ON *.* TO 'replicacion'@'192.168.1.12' IDENTIFIED BY 'BFp7yv1wjqTxg5TLKha0';
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
UNLOCK TABLES;
QUIT;

En el paso de SHOW MASTER STATUS se nos deberia mostrar una tabla como la siguiente:

+——————+———-+—————–+——————+
| File             | Position | Binlog_Do_DB    | Binlog_Ignore_DB |
+——————+———-+—————–+——————+
| mysql-bin.000001 |      107 | web             |                  |
+——————+———-+—————–+——————+
1 row in set (0.00 sec)

En el servidor 2

Ahora vamos a configurar el servidor 2, igualmente modificaremos /etc/mysql/my.cnf y si queremos solo un Master-Slave con indicar server-id = 2 es suficiente pero para un Master-Master además de eso necesitamos activar también los registros binarios y modificar el autoincremental para que cuente de 2 en 2 mientras en el maestro cuente de 1 en 1 para evitar que un INSERT concurrente calcule el mismo valor autoincremental:
server-id = 2
auto_increment_increment = 2
auto_increment_offset = 1
log_bin = /var/log/mysql/mysql-bin.og
binlog_do_db = web
sync_binlog = 1

Guardamos los cambios y reiniciamos MySQL igual que antes. Si tu base de datos no esta vacia sino que tienes un servidor que ya tenia datos ahora, antes de continuar, necesitas importar en el servidor 2 los datos del servidor 1. Ahora conectamos a MySQL para indicarle el maestro y preparar el usuario con el que el servidor 1 hará de esclavo de servidor 2:

mysql -u root -p

STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='192.168.1.11', MASTER_USER='replicacion', MASTER_PASSWORD='BFp7yv1wjqTxg5TLKha0', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=417;
START SLAVE;

Con eso tendríamos a servidor 2 como esclavo de servidor 1, notar que en MASTER_LOG_FILE y MASTER_LOG_POS debeis indicar la información que mostro SHOW MASTER STATUS en el servidor 1. Continuamos para crear el usuario con el que se conectará servidor 2 al servidor 1:
GRANT REPLICATION SLAVE ON *.* TO 'replicacion'@'192.168.1.11' IDENTIFIED BY 'BFp7yv1wjqTxg5TLKha0';
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
UNLOCK TABLES;
QUIT;

Volvemos al Servidor 1

Igual que antes, recordar la información que muestre SHOW MASTER STATUS porque es necesaria para hacer a servidor 1 esclavo de servidor 2. Modificaremos en el servidor 1 en /etc/mysql/my.cnf el autoincremental como hicimos con el servidor 2:

auto_increment_increment = 1
auto_increment_offset = 2

Servidor 1 contará de uno en uno pero empezara en el 2 como servidor 2 empieza en el 1, para evitar problemas con el primer INSERT de una tabla. Reiniciamos el MySQL del servidor 1 y nos conectamos para configurarlo como esclavo de 2.

mysql -u root -p

STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='192.168.1.12', MASTER_USER='replicacion', MASTER_PASSWORD='BFp7yv1wjqTxg5TLKha0', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=307;
START SLAVE;

Recordad en MASTER_LOG_FILE y MASTER_LOG_POS poner la información obtenida de SHOW MASTER STATUS en el servidor 2. Ahora para comprobar que estan conectando bien ejecutamos en la consola MySQL conectado a cada uno:
SHOW SLAVE STATUS G;

Y entre las líneas que muestra deberiamos ver:
Slave_IO_State: Waiting for master to send event

Indicando que esta conectado al maestro y esperando que le envie eventos cuando algo cambie. En caso de que no puedan conectar hay que comprobar con ping y traceroute que hay se pueden alcanzar el uno al otro, probar desde un servidor conectar al MySQL del otro, y que la clave de el usuario usado para la replicacion no sea superior a 32 caracteres (claves superiores a 32 caracteres esta dando problemas en las versiones actuales de MySQL).
Cuando necesiteis crear bases de datos nuevas sincronizadas entre los servidores primero agregarlas a la configuración y reiniciar ambos servidores, luego en uno crear la base de datos e introducir los datos y ya estara replicandose.
Para agregarlas a la configuración de los servidores (/etc/mysql/my.cnf) debemos poner una línea para cada base de datos, al estilo:
binlog_do_db = web
binlog_do_db = web1
Este artículo es una ligera modificación del artículo original: Blog de JHG

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *