PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Implementazione di Switchover/Switchback in PostgreSQL 9.3.

Questo post istruisce i DBA sofisticati su come configurare un ambiente di passaggio e ritorno grazioso nell'elevata disponibilità di PostgreSQL. In primo luogo, grazie agli autori delle patch Heikki e Fujii per aver reso più semplice Switchover/Switchback in PostgreSQL 9.3.(Scusate se ho perso altri nomi).

Vorrei tentare di illustrarlo in breve prima di queste patch, tutti voi sapete che gli Standby sono componenti critici per ottenere un ripristino di emergenza rapido e sicuro. In PostgreSQL, il concetto di ripristino si occupa principalmente delle linee temporali per identificare una serie di segmenti WAL prima e dopo il PITR o la promozione di Standby per evitare la sovrapposizione dei segmenti WAL. Gli ID sequenza temporale sono associati ai nomi dei file di segmento WAL (ad es.:- In $PGDATA/pg_xlog/0000000C000000020000009E il segmento "0000000C" è l'ID sequenza temporale). In Streaming Replication sia Primary che Slave seguiranno lo stesso ID sequenza temporale, tuttavia quando Standby ottiene la promozione come nuovo master tramite Switchover, aumenta l'ID sequenza temporale e il vecchio Primario si rifiuta di riavviarsi come Standby a causa della differenza di ID sequenza temporale e genera un messaggio di errore come:

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.

Pertanto, è necessario creare un nuovo Standby da zero, se la dimensione del database è enorme, è necessario un tempo più lungo per ricostruire e per questo periodo il nuovo Primario promosso funzionerà senza Standby. C'è anche un altro problema come, quando si verifica il passaggio, Primaria esegue l'arresto pulito, il processo Walsender invia tutti i record WAL in sospeso in standby ma non attende che vengano replicati prima di uscire. Walreceiver non applica i record WAL in sospeso poiché rileva la chiusura della connessione e le uscite.

Oggi, con due aggiornamenti software chiave in PostgreSQL 9.3, entrambi i problemi affrontati molto bene dagli autori e ora Streaming Replication Standby seguono costantemente un cambio di sequenza temporale. Ora possiamo passare in modo semplice e indolore dai compiti tra Primario e Standby semplicemente riavviando e riducendo notevolmente i tempi di ricostruzione di Standby.

Nota:il passaggio/ritorno non è possibile se gli archivi WAL non sono accessibili a entrambi i server e nel processo di passaggio il database primario deve eseguire uno spegnimento pulito (modalità normale o veloce).

Per fare una dimostrazione, iniziamo con l'installazione di Streaming Replication (wiki per configurare SR) che ho configurato nella mia macchina virtuale locale tra due cluster (5432 come primario e 5433 come standby) che condividono una posizione comune degli archivi WAL, perché entrambi i cluster dovrebbero avere accesso completo di sequenza degli archivi WAL. Guarda l'istantanea condivisa di seguito con i dettagli della configurazione e l'ID sequenza temporale corrente per una migliore comprensione del concetto.

In questa fase tutti devono avere una solida comprensione del fatto che Switchover e Switchback sono attività pianificate. Ora l'impostazione SR in atto, possiamo scambiare i compiti di primario e standby come mostrato di seguito:

Passaggi del passaggio:

Passaggio 1. Esegui lo spegnimento pulito del Primario[5432] (-m veloce o intelligente)

[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

Passaggio 2. Verifica lo stato di sincronizzazione e di ripristino di Standby[5433] prima di promuoverlo:

[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 in completa sincronizzazione. A questo punto siamo sicuri di promuoverlo come Primario.
Fase 3. Apri lo Standby come nuovo primario tramite pg_ctl promuovi o creando un file 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

Standby è stato promosso come master ed è seguita una nuova sequenza temporale che puoi notare nei log.
Passaggio 4. Riavvia il vecchio Primary come standby e consenti di seguire la nuova timeline passando "recovery_target_timline='latest'" nel file $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 si esegue recovery.conf è molto chiaro che il vecchio Primary tenta di connettersi alla porta 5433 come nuovo Standby che punta alla posizione comune degli archivi WAL e viene avviato.

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

Passaggio 5. Verifica il nuovo stato di Standby.

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

Fantastico, senza alcuna reimpostazione abbiamo riportato la vecchia Primaria come nuova Standby.

Passaggi per il ritorno:

Passaggio 1. Spegnimento pulito del nuovo Primario [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

Passaggio 2. Verifica lo stato di sincronizzazione del nuovo Standby [5432] prima di promuovere.
Passaggio 3. Apri il nuovo Standby [5432] come principale creando un file trigger o promuovi pg_ctl.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ touch /tmp/primary_131_down.txt

Passaggio 4. Il riavvio ha interrotto il nuovo Primario [5433] come nuovo 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

Puoi verificare i log del nuovo 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

Molto bello, senza molto tempo abbiamo cambiato le funzioni dei server Primari e Standby. Puoi anche notare l'incremento degli ID della sequenza temporale dai registri per ogni promozione.

Come altri, tutti i miei post fanno parte della condivisione della conoscenza, qualsiasi commento o correzione è il benvenuto. 🙂