Replicação de bancos de dados MySQL. Introdução

Raramente um sistema de produção moderno dispensa a replicação do banco de dados. É uma ferramenta poderosa para melhorar o desempenho do sistema e a tolerância a falhas, e é muito importante para o desenvolvedor moderno ter pelo menos um conhecimento básico de replicação. Neste artigo, compartilharei alguns conhecimentos básicos de replicação e mostrarei um exemplo simples de configuração de replicação no MySQL usando Docker.



imagem



O que é replicação e por que ela é necessária



Por si só, a replicação se refere ao processo de sincronização de várias cópias de um objeto. Em nosso caso, tal objeto é o servidor de banco de dados e os dados em si são de maior valor. Se tivermos dois ou mais servidores e, de qualquer forma, mantivermos um conjunto sincronizado de dados neles, implementamos a replicação do sistema. Mesmo a opção manual c mysqldump -> mysql load



também é replicação.



Deve ser entendido que a replicação de dados em si não tem valor e é apenas uma ferramenta para resolver as seguintes tarefas:



  • melhorando o desempenho de leitura de dados. Com a ajuda da replicação, seremos capazes de manter várias cópias do servidor e distribuir a carga entre elas.
  • . , . , .
  • . , , , .
  • . , ( , ), , .
  • . , , .
  • . .


MySQL



O processo de replicação envolve a propagação de alterações de dados do servidor principal (normalmente referido como mestre, mestre ), para um ou mais servidores escravos (escravo, escravo ). Existem também configurações mais complexas, em particular com vários servidores mestre, mas para cada alteração em um servidor mestre específico, os mestres restantes tornam-se condicionalmente escravos e consomem essas alterações.



Em geral, a replicação do MySQL consiste em três etapas:



  1. O servidor mestre grava as alterações de dados no log. Esse log é chamado de log binário e as alterações são chamadas de eventos de log binários .
  2. O escravo copia as mudanças para o log binário em seu próprio, chamado relay log .
  3. O escravo reproduz as alterações do relay log, aplicando-as aos seus próprios dados.


Tipos de replicação



Existem duas abordagens fundamentalmente diferentes para replicação: comando por comando e linha por linha . No caso de replicação comando a comando, as solicitações de alteração de dados (INSERT, UPDATE, DELETE) são registradas no log mestre e os escravos reproduzem exatamente os mesmos comandos. Com a replicação linha por linha, o log irá alterar diretamente as linhas nas tabelas e as mesmas alterações reais serão aplicadas ao escravo.



Como não existe solução mágica, cada um desses métodos tem suas próprias vantagens e desvantagens. A replicação por comando é mais fácil de implementar e entender e reduz a carga no mestre e na rede. No entanto, a replicação por comando pode levar a efeitos imprevisíveis ao usar funções não determinísticas, como NOW (), RAND (), etc. Também pode haver problemas causados ​​por dados fora de sincronia entre mestre e escravo. A replicação linha por linha leva a resultados mais previsíveis, uma vez que as alterações reais dos dados são capturadas e reproduzidas. No entanto, esse método pode aumentar significativamente a carga no servidor mestre, que deve registrar todas as alterações no log e na rede pela qual essas alterações se propagam.



O MySQL suporta ambos os métodos de replicação, e o padrão (podemos dizer que o recomendado) mudou dependendo da versão. Versões modernas como o MySQL 8 usam replicação baseada em linha por padrão.



O segundo princípio de divisão das abordagens de replicação é o número de servidores principais... A presença de um servidor mestre implica que apenas ele aceita alterações de dados e é uma espécie de padrão a partir do qual as alterações já são propagadas para muitos escravos. No caso da replicação mestre-mestre, obtemos alguns lucros e problemas. Uma das vantagens, por exemplo, é que podemos oferecer aos clientes remotos do mesmo Sydney e Helsinque uma oportunidade igualmente rápida de gravar suas alterações no banco de dados. Isso leva à principal desvantagem se ambos os clientes alteraram simultaneamente os mesmos dados, cujas alterações são consideradas finais, cuja transação é confirmada e cuja transação é revertida.



Além disso, é importante notar que a presença de um mestre de replicação mestre geralmente não pode aumentar o desempenho da gravação de dados no sistema. Vamos imaginar que nosso único mestre pode processar até 1000 solicitações por vez. Ao adicionar um segundo mestre replicado a ele, não poderemos processar 1000 solicitações em cada um deles, pois além de processar as solicitações “suas”, eles terão que aplicar as alterações feitas no segundo mestre. Isso, no caso da replicação comando a comando, fará com que a carga total possível em ambos não mais do que no mais fraco deles, e com a replicação linha por linha, o efeito não é totalmente previsível, pode ser positivo ou negativo, dependendo das condições específicas.



Um exemplo de construção de uma replicação simples em MySQL



Agora é a hora de criar uma configuração de replicação simples no MySQL. Para isso, usaremos as imagens Docker e MySQL do dockerhub , bem como o banco de dados mundial .



Para começar, lançaremos dois containers, um dos quais configuraremos posteriormente como master e o outro como slave. Vamos colocá-los em rede para que possam conversar uns com os outros.



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

      
      





A conexão de volume com o dump world.sql é especificada para o contêiner mestre para simular a presença de alguma base inicial nele. Ao criar um contêiner, o mysql baixará e executará scripts sql localizados no diretório docker-entrypoint-initdb.d.



Para trabalhar com arquivos de configuração, precisamos de um editor de texto. Qualquer um conveniente pode ser usado, eu prefiro 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

      
      





Em primeiro lugar, criaremos uma conta no mestre que será usada para replicação:



docker exec -it samplereplication-master mysql

      
      





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

      
      





A seguir, vamos alterar os arquivos de configuração do servidor mestre:



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

      
      





Os seguintes parâmetros devem ser adicionados ao arquivo my.cnf na seção [mysqld]:



server_id = 1 #     
log_bin = mysql-bin #       

      
      





Ao ativar / desativar o log binário, é necessário reiniciar o servidor. No caso do Docker, o contêiner é recarregado.



docker restart samplereplication-master

      
      





Certifique-se de que o log binário esteja ativado. Valores específicos como nome de arquivo e posição podem 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 a replicação de dados, é necessário “puxar” o escravo para o estado de mestre. Para fazer isso, você precisa bloquear temporariamente o próprio assistente para fazer um instantâneo dos dados reais.



mysql> FLUSH TABLES WITH READ LOCK;

      
      





A seguir, usando o mysqldump, vamos exportar dados do banco de dados. Claro, neste exemplo, você pode usar o mesmo world.sql, mas vamos nos aproximar de um cenário mais realista.



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

      
      





Depois disso, é necessário executar novamente o comando SHOW MASTER STATUS, e lembrar ou anotar os valores de Arquivo e Posição. Estas são as chamadas coordenadas do log binário. É a partir deles que iremos indicar para iniciar o escravo. Agora podemos desbloquear o mestre novamente:



mysql> UNLOCK TABLES;

      
      





O mestre está configurado e pronto para replicar para outros servidores. Vamos passar para o escravo agora. Em primeiro lugar, carregue o dump do master nele.



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

      
      





E então vamos mudar a configuração do escravo adicionando 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  #     “ ”

      
      





Depois disso, recarregue o escravo:



docker restart samplereplication-slave

      
      





E agora precisamos dizer ao escravo qual servidor será o mestre para ele e onde começar a replicar os dados. Em vez de MASTER_LOG_FILE e MASTER_LOG_POS, você deve substituir os valores obtidos de SHOW MASTER STATUS no master. Esses parâmetros são chamados coletivamente de coordenadas de log binárias.



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

      
      





Vamos começar a reproduzir o relay log e verificar o status de replicação:



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

      
      





SLAVE STATUS
*************************** 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)
      
      







Se tudo correr bem, seu status deve ser semelhante. Parâmetros chave aqui:



  • Slave_IO_State - na verdade, o estado de replicação.
  • Read_Master_Log_Pos é a última posição lida do log mestre.
  • Relay_Master_Log_File - O arquivo de log mestre atual.
  • Seconds_Behind_Master - atraso do escravo atrás do mestre, em segundos.
  • Last_IO_Error , Last_SQL_Error - erros de replicação, se houver.


Vamos tentar alterar os dados no mestre:



docker exec -it samplereplication-master mysql

      
      





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

      
      





E verifique se eles apareceram no escravo.



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! O registro inserido também é visível no escravo. Parabéns, agora você criou sua primeira replicação do MySQL!



Conclusão



Espero que, dentro da estrutura deste artigo, eu tenha conseguido dar uma compreensão básica dos processos de replicação, familiarizar-me com o uso desta ferramenta e tentar implementar de forma independente um exemplo simples de replicação em MySQL. O tópico da replicação, e sua aplicação prática, é extremamente extenso, e se você estiver interessado neste tópico, posso recomendar as seguintes fontes de estudo:



  • Relatório "How MySQL Replication Works", de Andrey Aksenov (Sphinx)
  • O livro “MySQL ao máximo. Otimização, replicação, backup "- Baron Schwartz, Petr Zaitsev, Vadim Tkachenko
  • "Highload" - aqui você pode encontrar receitas específicas para replicação de dados


Espero que você tenha achado este artigo útil e agradecemos seus comentários e comentários



All Articles