PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Implementando Switchover/Switchback no PostgreSQL 9.3.

Esta postagem educa DBAs sofisticados sobre como configurar um ambiente de transição e retorno de retorno gracioso na alta disponibilidade do PostgreSQL. Em primeiro lugar, obrigado aos autores do patch Heikki e Fujii por tornarem o Switchover/Switchback mais fácil no PostgreSQL 9.3.(Perdoe-me se eu perdi outros nomes).

Deixe-me tentar ilustrá-lo resumidamente antes desses patches, todos vocês sabem que o Standby é um componente crítico para alcançar uma recuperação de desastres rápida e segura. No PostgreSQL, o conceito de recuperação lida principalmente com linhas de tempo para identificar uma série de segmentos WAL antes e depois do PITR ou promoção de Standby para evitar a sobreposição de segmentos WAL. O ID da linha do tempo está associado aos nomes dos arquivos do segmento WAL (por exemplo:- Em $PGDATA/pg_xlog/0000000C000000020000009E o segmento "0000000C" é o ID da linha do tempo). Na Replicação de Streaming, o Primário e o Escravo seguirão o mesmo ID da linha do tempo, no entanto, quando o Standby é promovido como novo mestre pelo Switchover, ele colide com o ID da linha do tempo e o Primário antigo se recusa a reiniciar como Standby devido à diferença do ID da linha do tempo e lança uma mensagem de erro como:
FATAL:  requested timeline 10 is not a child of this server's history
DETAIL: Latest checkpoint is at 2/9A000028 on timeline 9, but in the history of the requested timeline, the server forked off from that timeline at 2/99017E68.

Assim, um novo Standby deve ser construído do zero, se o tamanho do banco de dados for grande, então um tempo maior para reconstruir e, para esse período, o Primary recém-promovido estará em execução sem Standby. Há também outro problema, como quando a alternância ocorre, o primário faz um desligamento limpo, o processo Walsender envia todos os registros WAL pendentes para o modo de espera, mas não espera que eles sejam replicados antes de sair. O Walreceiver não aplica esses registros WAL pendentes, pois detecta o fechamento da conexão e sai.

Hoje, com duas atualizações importantes de software no PostgreSQL 9.3, ambos os problemas foram muito bem resolvidos pelos autores e agora o Streaming Replication Standby segue uma mudança de linha do tempo de forma consistente. Agora podemos alternar de maneira simples e indolor as tarefas entre Primário e Standby apenas reiniciando e reduzindo consideravelmente o tempo de reconstrução do Standby.

Observação:a alternância/switchback não é possível se os arquivos WAL não estiverem acessíveis a ambos os servidores e no processo de alternância O banco de dados primário deve fazer um desligamento limpo (modo normal ou rápido).

Para demonstração, vamos começar com a configuração do Streaming Replication (wiki para configurar o SR) que configurei na minha VM local entre dois clusters (5432 como Primário e 5433 como Standby) compartilhando um local comum de arquivos WAL, porque ambos os clusters devem ter acesso completo de seqüência de arquivos WAL. Veja o instantâneo compartilhado abaixo com detalhes de configuração e ID da linha do tempo atual para entender melhor o conceito.

Nesta fase, todos devem ter um sólido entendimento de que Switchover e Switchback são atividades planejadas. Agora com a configuração do SR no lugar, podemos trocar as funções do primário e do standby, conforme mostrado abaixo:

Etapas de transição:

Etapa 1. Faça o desligamento limpo do primário [5432] (-m rápido ou inteligente)
[postgres@localhost:/~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data stop -mf
waiting for server to shut down.... done
server stopped

Etapa 2. Verifique o status de sincronização e o status de recuperação do Standby[5433] antes de promovê-lo:
[postgres@localhost:/opt/PostgreSQL/9.3~]$  psql -p 5433 -c 'select pg_last_xlog_receive_location() "receive_location",
pg_last_xlog_replay_location() "replay_location",
pg_is_in_recovery() "recovery_status";'
receive_location | replay_location | recovery_status
------------------+-----------------+-----------------
2/9F000A20 | 2/9F000A20 | t
(1 row)

Standby em total sincronia. Nesta fase, podemos promovê-lo como Primário.
Etapa 3. Abra o Standby como novo Primary por pg_ctl promote ou criando um arquivo de trigger.
[postgres@localhost:/opt/PostgreSQL/9.3~]$ grep trigger_file data_slave/recovery.conf
trigger_file = '/tmp/primary_down.txt'
[postgres@localhost:/opt/PostgreSQL/9.3~]$ touch /tmp/primary_down.txt

[postgres@localhost:/opt/PostgreSQL/9.3~]$ psql -p 5433 -c "select pg_is_in_recovery();"
pg_is_in_recovery
-------------------
f
(1 row)

In Logs:
2014-12-29 00:16:04 PST-26344-- [host=] LOG: trigger file found: /tmp/primary_down.txt
2014-12-29 00:16:04 PST-26344-- [host=] LOG: redo done at 2/A0000028
2014-12-29 00:16:04 PST-26344-- [host=] LOG: selected new timeline ID: 14
2014-12-29 00:16:04 PST-26344-- [host=] LOG: restored log file "0000000D.history" from archive
2014-12-29 00:16:04 PST-26344-- [host=] LOG: archive recovery complete
2014-12-29 00:16:04 PST-26342-- [host=] LOG: database system is ready to accept connections
2014-12-29 00:16:04 PST-31874-- [host=] LOG: autovacuum launcher started

O modo de espera foi promovido como mestre e uma nova linha do tempo foi seguida, que você pode observar nos registros.
Etapa 4. Reinicie o Primário antigo como espera e permita seguir a nova linha do tempo passando “recovery_target_timline='latest'” no arquivo $PGDATA/recovery.conf.
[postgres@localhost:/opt/PostgreSQL/9.3~]$ cat data/recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=localhost port=5433 user=postgres'
restore_command = 'cp /opt/PostgreSQL/9.3/archives93/%f %p'
trigger_file = '/tmp/primary_131_down.txt'
[postgres@localhost:/opt/PostgreSQL/9.3~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data start
server starting

Se você passar pelo recovery.conf, fica muito claro que o antigo primário está tentando se conectar à porta 5433 como novo Standby, apontando para o local comum dos arquivos WAL e iniciado.
In Logs:
2014-12-29 00:21:17 PST-32315-- [host=] LOG: database system was shut down at 2014-12-29 00:12:23 PST
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000E.history" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: entering standby mode
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000D00000002000000A0" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000D.history" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: consistent recovery state reached at 2/A0000090
2014-12-29 00:21:17 PST-32315-- [host=] LOG: record with zero length at 2/A0000090
2014-12-29 00:21:17 PST-32310-- [host=] LOG: database system is ready to accept read only connections
2014-12-29 00:21:17 PST-32325-- [host=] LOG: started streaming WAL from primary at 2/A0000000 on timeline 14

Etapa 5. Verifique o novo status de espera.
[postgres@localhost:/opt/PostgreSQL/9.3~]$ psql -p 5432 -c "select pg_is_in_recovery();"
pg_is_in_recovery
-------------------
t
(1 row)

Legal, sem nenhuma redefinição, trouxemos de volta o antigo primário como novo modo de espera.

Etapas de retorno:

Etapa 1. Faça o desligamento limpo do novo primário [5433]:
[postgres@localhost:/opt/~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_slave stop -mf
waiting for server to shut down.... done
server stopped

Etapa 2. Verifique o status de sincronização do novo Standby [5432] antes de promover.
Etapa 3. Abra o novo Standby [5432] como Primary criando um arquivo de trigger ou pg_ctl promote.
[postgres@localhost:/opt/PostgreSQL/9.3~]$ touch /tmp/primary_131_down.txt

Etapa 4. A reinicialização parou o novo Primário [5433] como novo Standby.
[postgres@localhost:/opt/PostgreSQL/9.3~]$ more data_slave/recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=localhost port=5432 user=postgres'
restore_command = 'cp /opt/PostgreSQL/9.3/archives93/%f %p'
trigger_file = '/tmp/primary_down.txt'

[postgres@localhost:/opt/PostgreSQL/9.3~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_slave start
server starting

Você pode verificar os logs do novo Standby.
In logs:
[postgres@localhost:/opt/PostgreSQL/9.3/data_slave/pg_log~]$ more postgresql-2014-12-29_003655.log
2014-12-29 00:36:55 PST-919-- [host=] LOG: database system was shut down at 2014-12-29 00:34:01 PST
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000F.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: entering standby mode
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000F.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000E00000002000000A1" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000E.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: consistent recovery state reached at 2/A1000090
2014-12-29 00:36:55 PST-919-- [host=] LOG: record with zero length at 2/A1000090
2014-12-29 00:36:55 PST-914-- [host=] LOG: database system is ready to accept read only connections
2014-12-29 00:36:55 PST-929-- [host=] LOG: started streaming WAL from primary at 2/A1000000 on timeline 15
2014-12-29 00:36:56 PST-919-- [host=] LOG: redo starts at 2/A1000090

Muito bom, sem muito tempo trocamos as funções dos servidores Primário e Standby. Você pode até notar o incremento dos IDs da linha do tempo dos logs para cada promoção.

Assim como outros todos os meus posts fazem parte do compartilhamento de conhecimento, quaisquer comentários ou correções são muito bem vindos. 🙂