1. O que é sincronização mestre-escravo?
A sincronização mestre-escravo significa backup redundante de dados. O banco de dados mestre (Master) sincroniza os dados de seu próprio banco de dados com o banco de dados escravo (Slave).
Pode haver uma biblioteca escrava ou várias bibliotecas escravas, conforme mostrado na figura:
2. Por que é necessária a sincronização mestre-escravo?
Embora o Redis possua tecnologia de persistência RDB e AOF, ele pode garantir que os dados na memória não serão perdidos quando o servidor for reiniciado (mas isso não significa que os dados não serão perdidos, ainda haverá indisponibilidade ao reiniciar).
Mas se o servidor desligar e nunca mais voltar a funcionar (por exemplo, falha de hardware), isso significa que os dados serão completamente perdidos! Isso terá um impacto significativo nos negócios.
Portanto, a necessidade da sincronização mestre-escravo reside na alta disponibilidade de dados. Ele garante que, quando uma máquina falhar, haja outros servidores disponíveis para failover.
A questão é: vários servidores compartilham redundantemente os mesmos dados.Como o Redis garante a consistência dos dados?
3. Como o Redis consegue a sincronização mestre-escravo?
Para resumir brevemente, existem dois pontos:
- Todas as modificações são feitas apenas na biblioteca principal: ou seja, a biblioteca principal pode ser lida e escrita, e a biblioteca escrava só pode ser lida e não escrita;
- As operações de gravação são sincronizadas do banco de dados mestre para o banco de dados escravo: sincronização completa e sincronização incremental.
(1) Sincronização completa
1. Estabeleça negociação e sincronização de conexão
1.1 Use o cliente redis-cli para conectar-se à biblioteca escrava, executar replicaof
o comando e especificar o IP e a porta da biblioteca principal;
1.2 Depois que a biblioteca escrava responder, execute o comando psync, que contém o runid da biblioteca principal e o deslocamento de replicação :
- runid: gera automaticamente um ID exclusivo aleatório na inicialização. Ao sincronizar pela primeira vez, o runid da biblioteca principal é desconhecido, então é
?
; - offset: Indica o progresso da replicação.Durante a primeira sincronização, seu valor é
-1
.
1.3 Após a biblioteca mestre receber o comando psync, FULLRESYNC
ela responde à biblioteca escrava com o comando, que também contém os dois parâmetros da biblioteca mestre runid e o deslocamento de replicação . A biblioteca escrava registrará esses dois parâmetros.
Nota: O comando replicaof é equivalente ao comando slaveof.Antes do Redis 5.0, o comando slaveof era usado.
2. Sincronização RDB
2.1 A biblioteca principal executa bgsave
o comando, neste momento fork
o subprocesso irá gerar um arquivo RDB, e o novo comando será gravado no buffer;
2.2 Envie arquivos RDB para a biblioteca escrava;
2.3 Após limpar os dados do banco de dados, carregue o arquivo RDB.
Nota 1: Para garantir a consistência dos dados,
bgsave
após a execução, a biblioteca principal continuará gravando novos comandos no buffer até que a biblioteca escrava carregue o RDB;Nota 2: bgsave cria um subprocesso, que é responsável de forma independente pela geração de RDB.Durante o processo de geração de RDB, a biblioteca principal do Redis não será bloqueada e a biblioteca principal ainda poderá processar comandos normalmente.
3. Sincronização de comandos
3.1 Após concluir o carregamento do RDB, a biblioteca escrava responderá uma mensagem de confirmação à biblioteca mestre, e a biblioteca mestre enviará o comando de gravação do buffer para a biblioteca escrava;
3.2 A biblioteca escrava recebe o comando de gravação da biblioteca mestre e o executa para tornar os dados mestre-escravo consistentes.
Nota: Após a execução do comando, a conexão longa será mantida e o comando de operação de gravação estará sempre sincronizado para garantir a consistência dos dados mestre-escravo;
Este processo também é chamado de "propagação de comando baseada em conexões longas".
(2) Sincronização incremental
Durante o processo de propagação do comando, se ocorrer uma falha na rede e a conexão for desconectada, novos comandos de gravação não serão sincronizados com a biblioteca escrava neste momento.
Mesmo que a conexão de rede seja desconectada e restaurada após o jitter, a conexão TCP foi desconectada neste momento e os dados definitivamente precisam ser ressincronizados.
- Antes do Redis 2.8, o banco de dados escravo só podia reiniciar a sincronização completa com o banco de dados mestre. Para arquivos RDB maiores, o tempo de recuperação da rede seria maior;
- A partir do Redis 2.8, a biblioteca escrava suporta sincronização incremental. Somente comandos de gravação que não ocorreram quando desconectados serão sincronizados com a biblioteca escrava.
O processo detalhado é o seguinte:
- Após a rede ser restaurada, a biblioteca escrava emite um comando psync para a biblioteca principal, carregando o runid retornado anteriormente pela biblioteca principal e o deslocamento copiado;
- Após a biblioteca principal receber o comando, ela verifica o runid e o deslocamento e responde ao
CONTINUE
comando se não houver problema; - A biblioteca mestre envia o comando de gravação durante o período de desconexão da rede, e a biblioteca escrava recebe o comando e o executa.
Na verdade, a biblioteca principal faz duas coisas durante o processo de propagação do comando:
- Envie o comando de gravação para a biblioteca escrava;
- Os comandos de gravação são gravados no
repl_backlog_buffer
buffer do backlog de replicação , que contém os comandos de gravação propagados mais recentemente.
O buffer de backlog de cópia é um buffer de anel. Além de repl_backlog_buffer, a biblioteca principal também possui o ponto de replicação master_repl_offset;
Da mesma forma, a biblioteca escrava também possui o ponto de cópia slave_repl_offset;
Se o deslocamento for especificado pelo comando psync da biblioteca, os dados ainda serão armazenados no buffer repl_backlog_buffer, ou seja:
master_repl_offset - tamanho <slave_repl_offset, ou seja, o deslocamento mínimo da biblioteca mestre é menor que o deslocamento da biblioteca escrava, indicando que os dados ainda estão no buffer de anel.
Portanto, desde que o buffer da biblioteca principal seja grande o suficiente para acomodar o último comando de gravação (protocolo Redis), a sincronização incremental pode ser usada após uma interrupção da rede.
O padrão repl_backlog_buffer = 1 M. Se a quantidade de dados gravados for grande, como 1 M/s, obviamente, os dados do buffer do backlog de cópia serão inválidos após 1 segundo de falha da rede, portanto, seu valor deve ser aumentado.
O tamanho específico precisa ser determinado de acordo com a situação real. Recomenda-se configurá-lo para mais de 10M, o que provavelmente é uma interrupção em 10 segundos, pois também leva um certo tempo para iniciar o servidor Redis.