poniedziałek, 29 września 2014

Promowanie serwera standby po awarii primary - PostgreSQLu

Ten post jest następstwem dość już starego innego posta "Tworzenie replikacji primary-standby w PostgreSQLu" aby uzupełnić małe braki w przypadku awarii mastera. Stworzyliśmy w nim replikację z jednym serwerem primary (read/write) i jednym serwerem standby w trybie hot_standby (tylko read). Oto przykładowy schemat architektury:


Doszło jednak do awarii i musimy dać użytkownikom naszego systemu możliwość zmian danych - czyli musimy zmienić działanie naszego standby na działającego primary i przekierować cały ruch na ten serwer.


Niestety PostgreSQL nie ma oprogramowania do identyfikacji crashu mastera i automatycznego promowania slava. Musimy zrobić to ręcznie (Na szczęście są narzędzia, które mogą nam w tym pomóc).

W poniższym przykładzie mamy dwie działające instancje na tej samej maszynie. Master pracuje na standardowym porcie, czyli 5432, a slave na porcie 6432. Sprawdźmy je aby mieć pewność, że działają tak jak chcemy:

[root@amsterdam /var/lib/pgsql]$ psql test
psql (9.3.5)
Wpisz "help" by uzyskać pomoc.

test=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 wiersz)

test=# select name, setting from pg_settings where name = 'port';
 name | setting 
------+---------
 port | 5432
(1 wiersz)

test=# \q
[root@amsterdam /var/lib/pgsql]$ psql -p6432 test
psql (9.3.5)
Wpisz "help" by uzyskać pomoc.

test=# select name, setting from pg_settings where name = 'port';
 name | setting 
------+---------
 port | 6432
(1 wiersz)

test=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 wiersz)

Jedenym ze sposobów inicjonowania procesu failover, jest dodanie do pliku recovery.conf informacji o pliku triggera:

[root@amsterdam /var/lib/pgsql/9.3/data4]$ cat recovery.done 
standby_mode = 'on'
primary_conninfo = 'user=replication password=replication host=127.0.0.1 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres'

trigger_file = '/var/lib/pgsql/psql.trigger.6432'


Zawartość pliku triggera ma znaczenie. Jeśli jest pusta lub zawiera słowo 'smart', standby zostanie podniesiony zaraz po zatwierdzeniu wszystkich dostępnych w katalogu archive plików WAL (Smart Failover). Jeśli jednak zawartość pliku będzie zawierać słowo 'fast', serwer ma zostać podniesiony natychmiast. Wszystkie pliki WAL, które nie zostały jeszcze zastosowane, będą ignorowane, a transakcję w nich zostaną utracone (Fast Failover).


Spróbujmy uruchomić proces Smart Failover:

[root@amsterdam /var/lib/pgsql]$ touch /var/lib/pgsql/psql.trigger.6432
[root@amsterdam /var/lib/pgsql]$ ll 9.3/data4/
razem 112
-rw------- 1 postgres postgres   208 09-25 05:09 backup_label.old
drwx------ 6 postgres postgres  4096 09-25 05:09 base
drwx------ 2 postgres postgres  4096 09-25 05:38 global
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_clog
-rw------- 1 postgres postgres  4309 09-25 05:09 pg_hba.conf
-rw------- 1 postgres postgres  1636 09-25 05:09 pg_ident.conf
drwx------ 2 postgres postgres  4096 09-25 05:36 pg_log
drwx------ 4 postgres postgres  4096 09-25 05:09 pg_multixact
drwx------ 2 postgres postgres  4096 09-25 05:36 pg_notify
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_serial
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_snapshots
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_stat
drwx------ 2 postgres postgres  4096 09-25 05:39 pg_stat_tmp
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_subtrans
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_tblspc
drwx------ 2 postgres postgres  4096 09-25 05:09 pg_twophase
-rw------- 1 postgres postgres     4 09-25 05:09 PG_VERSION
drwx------ 3 postgres postgres  4096 09-25 05:39 pg_xlog
-rw------- 1 postgres postgres 20573 09-25 05:11 postgresql.conf
-rw------- 1 postgres postgres    60 09-25 05:36 postmaster.opts
-rw------- 1 postgres postgres    74 09-25 05:36 postmaster.pid
-rw-r--r-- 1 postgres postgres   208 09-25 05:18 recovery.done

[root@amsterdam /var/lib/pgsql]$ psql -p6432 test
psql (9.3.5)
Wpisz "help" by uzyskać pomoc.

test=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 wiersz)

test=# select name, setting from pg_settings where name = 'port';
 name | setting 
------+---------
 port | 6432
(1 wiersz)

test=# \q

Serwer działający w trybie 'recovery mode' został tak zaprojektowany, aby odtwarzać dane po nieoczekiwanym zamknięciu. Plik recovery.conf definiuje jak znaleźć pliki logów transakcji i trzymać je dopóki nie są nam potrzebne. Wtedy serwer przechodzi w tryb normalny i sam generuje własne pliki logów transakcji. Gdy ten proces zostaje zakończony (failover), nazwa plik recovery.conf jest zmieniana na recovery.done.

Innym sposobem na promowanie slava na mastera, bez użycia pliku triggera, jest uruchomienie programu pg_ctl promote. Jako parametr podajemy katalog instancji slava (musimy to zrobić użytkownikiem nieuprzywilejowanym, który będzie właścicielem procesu):

[root@amsterdam /var/lib/pgsql/9.3]$ sudo su postgres
bash-4.2$ 
bash-4.2$ cd
bash-4.2$ /usr/pgsql-9.3/bin/pg_ctl promote -D /var/lib/pgsql/9.3/data5
serwer w trakcie rozgłaszania
bash-4.2$ 
bash-4.2$ psql -p6432 test
psql (9.3.5)
Wpisz "help" by uzyskać pomoc.

test=# select name, setting from pg_settings where name = 'port';
 name | setting 
------+---------
 port | 6432
(1 wiersz)

test=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 wiersz)

test=# \q


Widziałam wiele zapytań o automatyzację tego procesu na różnych forach internetowych. Pytanie jest tylko takie - czy jesteśmy w stanie napisać skrypt, który podjoł by decyzję, że serwer primary padł i aby system miał działać nadal musimy promować standby na jego miejsce? A może to był tylko problem sieciowy i niedługo wszystko wróci do normy. Czy nie lepiej aby to człowiek zdecydował, aby proces promowania rozpocząć i sam proces failover automatyzować.

Powodzenia i miłego testowania działania replikacji.