State Snapshot Transfer (SST) é uma das duas maneiras usadas pelo Galera para realizar a sincronização inicial quando um nó está ingressando em um cluster, até que o nó seja declarado como sincronizado e parte do “componente primário”. Dependendo do tamanho do conjunto de dados e da carga de trabalho, o SST pode ser extremamente rápido ou uma operação cara que deixará seu serviço de banco de dados de joelhos.
O SST pode ser realizado usando 3 métodos diferentes:
- mysqldump
- rsync (ou rsync_wan)
- xtrabackup (ou xtrabackup-v2, mariabackup)
Na maioria das vezes, xtrabackup-v2 e mariabackup são as opções preferidas. Raramente vemos pessoas rodando em rsync ou mysqldump em clusters de produção.
O problema
Quando o SST é iniciado, existem vários processos acionados no nó joiner, que são executados pelo usuário "mysql":
$ ps -fu mysql
UID PID PPID C STIME TTY TIME CMD
mysql 117814 129515 0 13:06 ? 00:00:00 /bin/bash -ue /usr//bin/wsrep_sst_xtrabackup-v2 --role donor --address 192.168.55.173:4444/xtrabackup_sst//1 --socket /var/lib/mysql/mysql.sock --datadir
mysql 120036 117814 15 13:06 ? 00:00:06 innobackupex --no-version-check --tmpdir=/tmp/tmp.pMmzIlZJwa --user=backupuser --password=x xxxxxxxxxxxxxx --socket=/var/lib/mysql/mysql.sock --galera-inf
mysql 120037 117814 19 13:06 ? 00:00:07 socat -u stdio TCP:192.168.55.173:4444
mysql 129515 1 1 Oct27 ? 01:11:46 /usr/sbin/mysqld --wsrep_start_position=7ce0e31f-aa46-11e7-abda-56d6a5318485:4949331
Enquanto estiver no nó doador:
mysql 43733 1 14 Oct16 ? 03:28:47 /usr/sbin/mysqld --wsrep-new-cluster --wsrep_start_position=7ce0e31f-aa46-11e7-abda-56d6a5318485:272891
mysql 87092 43733 0 14:53 ? 00:00:00 /bin/bash -ue /usr//bin/wsrep_sst_xtrabackup-v2 --role donor --address 192.168.55.172:4444/xtrabackup_sst//1 --socket /var/lib/mysql/mysql.sock --datadir /var/lib/mysql/ --gtid 7ce0e31f-aa46-11e7-abda-56d6a5318485:2883115 --gtid-domain-id 0
mysql 88826 87092 30 14:53 ? 00:00:05 innobackupex --no-version-check --tmpdir=/tmp/tmp.LDdWzbHkkW --user=backupuser --password=x xxxxxxxxxxxxxx --socket=/var/lib/mysql/mysql.sock --galera-info --stream=xbstream /tmp/tmp.oXDumYf392
mysql 88827 87092 30 14:53 ? 00:00:05 socat -u stdio TCP:192.168.55.172:4444
SST contra um grande conjunto de dados (centenas de GBytes) não é divertido. Dependendo do hardware, rede e carga de trabalho, pode levar horas para ser concluído. Os recursos do servidor podem ficar saturados durante a operação. Apesar da limitação ser suportada no SST (somente para xtrabackup e mariabackup) usando as opções --rlimit e --use-memory, ainda estamos expostos a um cluster degradado quando você está ficando sem a maioria dos nós ativos. Por exemplo, se você tiver o azar de se encontrar com apenas um dos três nós em execução. Portanto, é aconselhável realizar o SST durante as horas de silêncio. No entanto, você pode evitar o SST executando algumas etapas manuais, conforme descrito nesta postagem do blog.
Parando um SST
A interrupção de um SST precisa ser feita nos nós doador e associador. O joiner aciona o SST depois de determinar o tamanho da lacuna ao comparar o seqno Galera local com o seqno do cluster. Ele executa o wsrep_sst_{wsrep_sst_method} comando. Isso será escolhido pelo doador escolhido, que começará a transmitir dados para o marceneiro. Um nó doador não tem capacidade de se recusar a servir a transferência de instantâneo, uma vez selecionado pela comunicação do grupo Galera ou pelo valor definido em wsrep_sst_donor variável. Uma vez iniciada a sincronização e você deseja reverter a decisão, não há um único comando para interromper a operação.
O princípio básico ao parar um SST é:
- Faça o marceneiro parecer morto a partir de um ponto de vista de comunicação do grupo Galera (desligar, bloquear, bloquear, reiniciar, desconectar cabo, lista negra etc.)
- Elimine os processos SST no doador
Alguém poderia pensar que matar o processo innobackupex (kill -9 {innobackupex PID}) no doador seria suficiente, mas esse não é o caso. Se você matar os processos SST no doador (ou joiner) sem isolar o joiner, o Galera ainda poderá ver o joiner como ativo e marcará o processo SST como incompleto, reaparecendo assim um novo conjunto de processos para continuar ou recomeçar. Você estará de volta à estaca zero. Este é o comportamento esperado do script /usr/bin/wsrep_sst_{method} para proteger a operação SST que é vulnerável a tempos limite (por exemplo, se for de longa duração e uso intensivo de recursos).
Vejamos um exemplo. Temos um nó de junção com falha que gostaríamos de reingressar no cluster. Começaríamos executando o seguinte comando no joiner:
$ systemctl start mysql # or service mysql start
Um minuto depois, descobrimos que a operação estava muito pesada naquele momento específico e decidimos adiá-la mais tarde durante o horário de baixo tráfego. A maneira mais direta de interromper um método SST baseado em xtrabackup é simplesmente desligar o nó do joiner e matar os processos relacionados ao SST no nó doador. Alternativamente, você também pode bloquear as portas de entrada no joiner executando o seguinte comando iptables no joiner:
$ iptables -A INPUT -p tcp --dport 4444 -j DROP
$ iptables -A INPUT -p tcp --dport 4567:4568 -j DROP
Em seguida, no doador, recupere o PID dos processos SST (liste os processos pertencentes ao usuário "mysql"):
$ ps -u mysql
PID TTY TIME CMD
117814 ? 00:00:00 wsrep_sst_xtrab
120036 ? 00:00:06 innobackupex
120037 ? 00:00:07 socat
129515 ? 01:11:47 mysqld
Finalmente, mate todos eles, exceto o processo mysqld (você deve ser extremamente cuidadoso para NÃO matar o processo mysqld no doador!):
$ kill -9 117814 120036 120037
Em seguida, no log de erros do MySQL doador, você deve observar a seguinte linha aparecendo após ~ 100 segundos:
2017-10-30 13:24:08 139722424837888 [Warning] WSREP: Could not find peer: 42b85e82-bd32-11e7-87ae-eff2b8dd2ea0
2017-10-30 13:24:08 139722424837888 [Warning] WSREP: 1.0 (192.168.55.172): State transfer to -1.-1 (left the group) failed: -32 (Broken pipe)
Nesse ponto, o doador deve retornar ao estado "sincronizado", conforme relatado por wsrep_local_state_comment e o processo SST é completamente interrompido. O doador está de volta ao seu estado operacional e é capaz de atender os clientes em plena capacidade.
Para o processo de limpeza no joiner, você pode simplesmente liberar a cadeia iptables:
$ iptables -F
Ou simplesmente remova as regras com o sinalizador -D:
$ iptables -D INPUT -p tcp --dport 4444 -j DROP
$ iptables -D INPUT -p tcp --dport 4567:4568 -j DROP
A abordagem semelhante pode ser usada com outros métodos SST como rsync, mariabackup e mysqldump.
Limitando um SST (somente método xtrabackup)
Dependendo de quão ocupado o doador estiver, é uma boa abordagem acelerar o processo SST para que não afete significativamente o doador. Vimos vários casos em que, durante falhas catastróficas, os usuários estavam desesperados para trazer de volta um cluster com falha como um único nó inicializado e deixar o restante dos membros recuperar o atraso mais tarde. Essa tentativa reduz o tempo de inatividade do lado do aplicativo, no entanto, cria uma carga adicional nesse “cluster de um nó”, enquanto os membros restantes ainda estão inativos ou se recuperando.
O Xtrabackup pode ser limitado com --throttle=
[sst]
rlimit=128k
inno-apply-opts="--use-memory=200M"
Mais detalhes na página de documentação do Percona Xtrabackup SST.
No entanto, há um porém. O processo pode ser tão lento que nunca alcançará os logs de transação que o InnoDB está gravando, portanto, o SST pode nunca ser concluído. Geralmente, essa situação é muito incomum, a menos que você realmente tenha uma carga de trabalho de gravação muito intensa ou aloque recursos muito limitados ao SST.
Conclusões
O SST é crítico, mas pesado, e pode ser uma operação de longa duração, dependendo do tamanho do conjunto de dados e da taxa de transferência da rede entre os nós. Independentemente das consequências, ainda há possibilidades de interromper a operação para que possamos ter um melhor plano de recuperação em um momento melhor.