Replicación de bases de datos MySQL. Introducción

Rara vez un sistema de producción moderno prescinde de la replicación de bases de datos. Es una herramienta poderosa para mejorar el rendimiento del sistema y la tolerancia a fallas, y es muy importante para el desarrollador moderno tener al menos un conocimiento básico de la replicación. En este artículo, compartiré algunos conocimientos básicos de replicación y le mostraré un ejemplo simple de cómo configurar la replicación en MySQL usando Docker.



imagen



Qué es la replicación y por qué es necesaria



Por sí misma, la replicación se refiere al proceso de sincronizar múltiples copias de un objeto. En nuestro caso, dicho objeto es el servidor de la base de datos y los datos en sí son de mayor valor. Si tenemos dos o más servidores, y de alguna manera mantenemos un conjunto sincronizado de datos en ellos, hemos implementado la replicación del sistema. Incluso la opción c manual mysqldump -> mysql load



también es una replicación.



Debe entenderse que la replicación de datos en sí misma no tiene valor y es solo una herramienta para resolver las siguientes tareas:



  • mejorar el rendimiento de lectura de datos. Con la ayuda de la replicación, podremos mantener varias copias del servidor y distribuir la carga entre ellas.
  • . , . , .
  • . , , , .
  • . , ( , ), , .
  • . , , .
  • . .


MySQL



El proceso de replicación implica la propagación de cambios de datos desde el servidor principal (generalmente denominado maestro, maestro ), a uno o más servidores esclavos (esclavo, esclavo ). También hay configuraciones más complejas, en particular con varios servidores maestros, pero para cada cambio en un servidor maestro específico, los maestros restantes se convierten condicionalmente en esclavos y consumen estos cambios.



En general, la replicación de MySQL consta de tres pasos:



  1. El servidor maestro escribe los cambios de datos en el registro. Este registro se denomina registro binario y los cambios se denominan eventos de registro binario .
  2. El esclavo copia los cambios al registro binario en el suyo, llamado registro de retransmisión .
  3. El esclavo reproduce los cambios del registro del relé y los aplica a sus propios datos.


Tipos de replicación



Hay dos enfoques fundamentalmente diferentes para la replicación: comando por comando y fila por fila . En el caso de la replicación comando por comando, las solicitudes de cambio de datos (INSERT, UPDATE, DELETE) se registran en el registro maestro y los esclavos reproducen exactamente los mismos comandos. Con la replicación fila por fila, el registro cambiará directamente las filas en las tablas, y los mismos cambios reales se aplicarán al esclavo.



Como no existe una fórmula mágica, cada uno de estos métodos tiene ventajas y desventajas. La replicación por comando es más fácil de implementar y comprender, y reduce la carga en el maestro y en la red. Sin embargo, la replicación por comando puede producir efectos impredecibles cuando se utilizan funciones no deterministas como NOW (), RAND (), etc. También puede haber problemas causados ​​por datos no sincronizados entre el maestro y el esclavo. La replicación fila por fila conduce a resultados más predecibles, ya que los cambios de datos reales se capturan y reproducen. Sin embargo, este método puede aumentar significativamente la carga en el servidor maestro, que debe registrar cada cambio en el registro, y en la red a través de la cual se propagan estos cambios.



MySQL soporta ambos métodos de replicación, y el predeterminado (podemos decir que el recomendado) cambia dependiendo de la versión. Las versiones modernas como MySQL 8 usan la replicación basada en filas de forma predeterminada.



El segundo principio para dividir los enfoques de replicación es la cantidad de servidores maestros... La presencia de un servidor maestro implica que solo acepta cambios de datos, y es una especie de punto de referencia desde el cual los cambios ya se propagan a muchos esclavos. En el caso de la replicación maestro-maestro, obtenemos beneficios y problemas. Una de las ventajas, por ejemplo, es que podemos brindar a los clientes remotos de la misma Sydney y Helsinki una oportunidad igualmente rápida de escribir sus cambios en la base de datos. Esto conduce al principal inconveniente si ambos clientes cambiaron simultáneamente los mismos datos, cuyos cambios se consideran definitivos, cuya transacción se confirma y cuya transacción se revierte.



Además, vale la pena señalar que la presencia de un maestro de replicación maestro en general no puede aumentar el rendimiento de la escritura de datos en el sistema. Imaginemos que nuestro único maestro puede procesar hasta 1000 solicitudes a la vez. Al agregarle un segundo maestro replicado, no podremos procesar 1000 solicitudes en cada uno de ellos, ya que además de procesar “sus” solicitudes, tendrán que aplicar los cambios realizados en el segundo maestro. Eso, en el caso de la replicación comando por comando, hará que la carga total posible en ambos no sea mayor que en el más débil de ellos, y con la replicación fila por fila, el efecto no es del todo predecible, puede ser positivo o negativo, dependiendo de las condiciones específicas.



Un ejemplo de construcción de una replicación simple en MySQL



Ahora es el momento de crear una configuración de replicación simple en MySQL. Para ello usaremos las imágenes de Docker y MySQL de dockerhub , así como la base de datos mundial .



Para empezar lanzaremos dos contenedores, uno de los cuales luego configuraremos como maestro, y el segundo como esclavo. Vamos a conectarlos en red para que puedan hablar entre ellos.



docker run -d --name samplereplication-master -e MYSQL_ALLOW_EMPTY_PASSWORD=true -v ~/path/to/world/dump:/docker-entrypoint-initdb.d  mysql:8.0

docker run -d --name samplereplication-slave -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:8.0

docker network create samplereplication
docker network connect samplereplication samplereplication-master
docker network connect samplereplication samplereplication-slave

      
      





La conexión de volumen con el volcado world.sql se especifica para el contenedor maestro con el fin de simular la presencia de alguna base inicial en él. Al crear un contenedor, mysql descargará y ejecutará scripts sql ubicados en el directorio docker-entrypoint-initdb.d.



Para trabajar con archivos de configuración, necesitamos un editor de texto. Se puede usar cualquier que sea conveniente, prefiero vim.



docker exec samplereplication-master apt-get update && docker exec samplereplication-master apt-get install -y vim 
docker exec samplereplication-slave apt-get update && docker exec samplereplication-slave apt-get install -y vim

      
      





En primer lugar, creemos una cuenta en el maestro que se utilizará para la replicación:



docker exec -it samplereplication-master mysql

      
      





mysql> CREATE USER 'replication'@'%';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';

      
      





A continuación, cambiemos los archivos de configuración del servidor maestro:



docker exec -it samplereplication-master bash
~ vi /etc/mysql/my.cnf

      
      





Los siguientes parámetros deben agregarse al archivo my.cnf en la sección [mysqld]:



server_id = 1 #     
log_bin = mysql-bin #       

      
      





Al habilitar / deshabilitar el registro binario, se requiere reiniciar el servidor. En el caso de Docker, el contenedor se vuelve a cargar.



docker restart samplereplication-master

      
      





Asegúrese de que el registro binario esté habilitado. Los valores específicos, como el nombre del archivo y la posición, pueden variar.



mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      156 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

      
      





Para iniciar la replicación de datos, es necesario "levantar" el esclavo al estado del maestro. Para hacer esto, debe bloquear temporalmente el asistente para hacer una instantánea de los datos reales.



mysql> FLUSH TABLES WITH READ LOCK;

      
      





Luego, usando mysqldump, exportemos datos de la base de datos. Por supuesto, en este ejemplo, puede usar el mismo world.sql, pero acerquémonos a un escenario más realista.



docker exec samplereplication-master mysqldump world > /path/to/dump/on/host/world.sql

      
      





Después de eso, es necesario ejecutar nuevamente el comando SHOW MASTER STATUS y recordar o escribir los valores de Archivo y Posición. Estas son las llamadas coordenadas del registro binario. Es a partir de ellos que indicaremos además para iniciar el esclavo. Ahora podemos desbloquear el maestro nuevamente:



mysql> UNLOCK TABLES;

      
      





El maestro está configurado y listo para replicarse en otros servidores. Pasemos ahora al esclavo. En primer lugar, cargue en él el volcado obtenido del maestro.



docker cp /path/to/dump/on/host/world.sql samplereplication-slave:/tmp/world.sql
docker exec -it samplereplication-slave mysql
mysql> CREATE DATABASE `world`;
docker exec -it samplereplication-slave bash
~ mysql world < /tmp/world.sql

      
      





Y luego cambiaremos la configuración del esclavo agregando parámetros:



log_bin = mysql-bin  #      
server_id = 2  #   
relay-log = /var/lib/mysql/mysql-relay-bin #    
relay-log-index = /var/lib/mysql/mysql-relay-bin.index  #        
read_only = 1  #     “ ”

      
      





Después de eso, recargue el esclavo:



docker restart samplereplication-slave

      
      





Y ahora tenemos que decirle al esclavo qué servidor será el maestro y dónde comenzar a replicar los datos. En lugar de MASTER_LOG_FILE y MASTER_LOG_POS, debe sustituir los valores obtenidos de SHOW MASTER STATUS en el maestro. Estos parámetros se denominan colectivamente coordenadas de registro binario.



mysql> CHANGE MASTER TO MASTER_HOST='samplereplication-master', MASTER_USER='replication', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=156;

      
      





Comencemos a reproducir el registro de retransmisión y verifiquemos el estado de la replicación:



mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G

      
      





ESTADO DE ESCLAVO
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: samplereplication-master
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 156
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 324
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 156
              Relay_Log_Space: 533
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: c341beb7-3a33-11eb-9440-0242ac110002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)
      
      







Si todo salió bien, su estado debería ser similar. Parámetros clave aquí:



  • Slave_IO_State : en realidad, el estado de replicación.
  • Read_Master_Log_Pos es la última posición leída del registro maestro.
  • Relay_Master_Log_File : el archivo de registro maestro actual.
  • Seconds_Behind_Master : retraso del esclavo con respecto al maestro, en segundos.
  • Last_IO_Error , Last_SQL_Error : errores de replicación, si los hay.


Intentemos cambiar los datos en el maestro:



docker exec -it samplereplication-master mysql

      
      





mysql> USE world;
mysql> INSERT INTO city (Name, CountryCode, District, Population) VALUES ('Test-Replication', 'ALB', 'Test', 42);

      
      





Y compruebe si aparecieron en el esclavo.



docker exec -it samplereplication-slave mysql

      
      





mysql> USE world;
mysql> SELECT * FROM city ORDER BY ID DESC LIMIT 1;
+------+------------------+-------------+----------+------------+
| ID   | Name             | CountryCode | District | Population |
+------+------------------+-------------+----------+------------+
| 4081 | Test-Replication | ALB         | Test     |         42 |
+------+------------------+-------------+----------+------------+
1 row in set (0.00 sec)

      
      





¡Excelente! El registro introducido también es visible en el esclavo. ¡Felicitaciones, ha creado su primera replicación de MySQL!



Conclusión



Espero que en el marco de este artículo haya podido brindar una comprensión básica de los procesos de replicación, familiarizarme con el uso de esta herramienta e intentar implementar de forma independiente un ejemplo simple de replicación en MySQL. El tema de la replicación y su aplicación práctica es extremadamente extenso, y si está interesado en este tema, puedo recomendar las siguientes fuentes para estudiar:



  • Informe "Cómo funciona la replicación de MySQL" por Andrey Aksenov (Sphinx)
  • El libro “MySQL al máximo. Optimización, replicación, copia de seguridad "- Baron Schwartz, Petr Zaitsev, Vadim Tkachenko
  • "Highload" : aquí puede encontrar recetas específicas para la replicación de datos


Espero que haya encontrado útil este artículo y agradecemos sus comentarios y sugerencias.



All Articles