czwartek, 12 czerwca 2014

Tworzenie replikacji primary-standby w PostgreSQLu

Przyszedł w końcu czas postawienie replikacji master-slave w PostgreSQLu. Ten post jest kontynuacją poprzedniego posta na temat wprowadzenia do replikacji, który możecie przeczytać tutaj. Przypominam, że ten system bazodanowy nie ma jeszcze replikacji master-master, ale jeśli by wam bardzo na tym zależało, to proponuje się zapoznać z projektem Bucardo, który daje taką możliwość.

Do postawienia PostgreSQLowej replikacji wykorzystam dwie maszyny:
  • Serwer A: zlokalizowany w Nowym Jorku, host: HOST-A
  • Serwer B: zlokalizowany w Amsterdamie, host: HOST-B

Zakładam, że serwer B będzie masterem, a serwer A slavem. Opisywałam już w poprzednich postach jak zainstalować serwer PostgreSQL dlatego zakładam, że spokojnie mogę pominąć ten krok. Jeśli jednak potrzebujecie pomocy w tych krokach, odsyłam do poprzednich postów gdzie opisuje instalację ze źródeł lub z paczki.

Konfigurujemy Master serwer (serwer B)

Na maszynie B działa już serwer z którego chcemy 'zrobić' mastera i dołączyć do niego tylko serwer standby. Dlatego zajmiemy się tylko konfiguracją. Zmieniamy główny plik konfiguracyjny PostgreSQLa postgresql.conf:

listen_addresses = '*'
wal_level = hot_standby 
archive_mode = on 
archive_command = 'cp %p /var/lib/pgsql/9.3/archive/%f'


#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------

# - Sending Server(s) -

# Set these on the master and on any standby that will send replication data.
max_wal_senders = 1
wal_keep_segments = 32
#wal_sender_timeout = 60s


Nie wszystkie z wymienionych opcji muszą być zmienione:
  • listen_addesses - z jakich adresów można się łączyć do serwera. Jeśli nie chcemy aby PostgreSQL słuchał na wszystkich adresach tak jak jest to na przykładzie ('*'), możemy wyszczególnić o jakie dokładnie adresy IP chodzi.
  • wal_level - wskazuje ile informacji ma być zapisywanych do plików WAL. minimal wskazuje na minimalna ilość informacji, która może tylko być pomocna przy procesie recovery po crashu serwera lub natychmiastowym zamknięciu. Nie pozwala jednak na rekonstrukcję danych. Do tego potrzebny jest poziom archive. Różnica między archive a hot_standby jest taka, że przy tym drugim zapisywane są dodatkowe informację potrzebne do zrekonstruowania statusu działającej transakcji z plików WAL. Poziom hot_standby jest wymagany aby działała Stream Replikacja.
  • archive_mode [NO/OFF] - Jeśli jest włączona, pliki WAL, które zostały w całości skompletowane, są wysyłane do archiwizacji przy użyciu polecenia zdefiniowanego przez archive_command. Ta opcja musi być włączona aby wal_level = archive lub hot_standby miał jakiś skutek.
  • archive_command - polecenie do archiwizacji plików WAL
  • max_wal_senders - definiuje maksymalną ilość połączeń z serwerów standby lub klientów programu do tworzenia base backupu. Domyśle ta liczba jest równa 0 co oznacza, że replikacja jest wyłączona.
  • wal_keep_segments - definiuje minimalną ilość starych plików logów segmentów trzymanych w katalogu pg_xlog
  • wal_sender_timeout - definiuje ile sekund ma upłynąć zanim zostanie zakończone połączenie replikacji, które jest nieaktywne. Ta opcja może być pomocna przy sprawdzaniu czy standby nie padł lub braku połączenia sieciowego. Przy wartości 0 ten mechanizm jest wyłączony.

Aby slave mógł pobierać dane z mastera, stworzymy użytkownika z prawami do logowania i replikacji lub musi to być superuser. (Nasz nowy user ma dostęp do strumieniowanych plików WAL czyli ma bardzo wysokie prawa dostępu ale nie ma możliwości dokonywania zmian na serwerze primary):

CREATE USER replication REPLICATION LOGIN CONNECTION LIMIT 1 ENCRYPTED PASSWORD 'replication';

Naszym celem jest stworzenie replikacji primary z jednym serwerem standby. Dlatego stworzony user ma ograniczenie do jednego połączenia na raz do serwera. Jeśli chcesz podłączyć więcej slavów do mastera, musisz zupdatować usera replication (zwiększając limit połączeń) lub stworzyć nowego usera.

Zmieniamy w pliku autoryzacji pg_hba.conf do serwera:

# Allow replication connections from localhost, by a user with the
# replication privilege.
host replication replication HOST-A/32 md5

Możemy uruchomić serwer.

Stawianie i konfiguracja serwera Standby (serwer A)

Ze względu na specyfikę działania replikacji w PostgreSQLu pliki danych binarnych muszą być takie same na serwerze Standby i Primary. Od wersji 9.1 dostępny jest i rekomendowany program pg_basebackup, który wykonuje binarną kopię plików klastra. Backup jest tworzony przy wykorzystaniu zwykłego połączenia do PostgreSQL i przy wykorzystaniu protokołu replikacji (Serwer primary musi mieć ustawiony max_wal_senders min = 1 aby połączenie doszło do skutku).

[root@niujork /home/postgres/psql9.3.4]$ mkdir data4
[root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4
[root@niujork /home/postgres/psql9.3.4]$ /usr/local/pgsql/bin/pg_basebackup -R -D /home/postgres/psql9.3.4/data4 --host=HOST-B -Ureplication -W
Password: 
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
[root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4

Program utworzył w katalogu data4 całą nową strukturę klastra i dodał nowy plik recovery.conf (opcja -R) z ustawieniami do uruchomienia Streaming Replication. Opcja -D wskazuje katalog docelowy gdzie klaser ma zostać 'zainstalowany'. Więcej na temat tego programu w dokumentacji tutaj.

[root@niujork /home/postgres/psql9.3.4/data4]$ cat recovery.conf 
standby_mode = 'on'
primary_conninfo = 'user=replication password=replication host=HOST-B port=5432 sslmode=disable sslcompression=1'

To zmienna standby_mode = 'on' świadczy o tym, że serwer PostgreSQL działa jako standby. Jeśli zmienna jest równa 'off' wszystkie inne już nie są brane pod uwagę. Zmienna primary_conninfo trzyma informację na temat połączenia do mastera. Przypominam, że user którego użyjemy musi być seperuser-em lub użytkownikiem z prawami do replikacji. Dane zostały automatycznie wypełnione przy skopiowaniu klastra przez pg_basebackup.

Nasz nowy serwer ma taki sam plik konfiguracyjny jak jego master, z którego została wykonana kopia klastra (możemy go zmienić i dostosować do własnych potrzeb). Aby było możliwe querowanie (tylko read-only) na serwerze standby, w pliku konfiguracyjnym postgresql.conf musimy mieć włączoną opcję:

# - Standby Servers -
# These settings are ignored on a master server.
hot_standby = on 

  • hot_standby - [ON/OFF] - Jeśli serwer jest włączony jako standby (standby_mode = 'on') i hot_standby = 'on' jest możliwe podłączenie się do serwera i wykonywanie poleceń read-only. 


Sprawdzenie działania replikacji

PostgreSQL udostępnia kilka prostych funkcji do sprawdzania statusu replikacji:
  • pg_is_in_recovery - funkcja do sprawdzania czy serwer działa w trybie recovery lub czy jest slavem
  • pg_last_xlog_receive_location - funkcja zwraca ostatnią lokalizację logu transakcji otrzymaną i zsynchronizaowaną na dysku przez stream replikację 
  • pg_last_xlog_replay_location - funkcja zwraca ostatnią lokalizację logu transakcji powtórzoną w trakcie recovery. Jeśli serwer wystartował normalnie bez recovery, funkcja zwróci NULL.
  • pg_last_xact_replay_timestamp - funkcja zwraca timestamp ostatniej transakcji powtarzanej w trakcie recovery
  • pg_xlogfile_name_offset - funkcja zwraca nazwę i offset pliku WAL pytanej lokalizacji transakcji
Od wersji 9.1 dostępny jest także widok do sprawdzania na serwerze primary stanu replikacji:

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 31416
usesysid         | 16387
usename          | replication
application_name | walreceiver
client_addr      | HOST-A
client_hostname  | 
client_port      | 46924
backend_start    | 2014-06-11 05:53:51.971246-04
state            | streaming
sent_location    | 0/25008A08
write_location   | 0/25008A08
flush_location   | 0/25008A08
replay_location  | 0/25008A08
sync_priority    | 0
sync_state       | async

postgres=# SELECT * FROM pg_xlogfile_name_offset('0/25008A08');
        file_name         | file_offset 
--------------------------+-------------
 000000010000000000000025 |       35336
(1 row)



Tylko czy jesteśmy w stanie realnie sprawdzić jak bardzo nasz slave jest do tyłu w stosunku do mastera? Szukając dalej natknęłam się na ciekawy post (Monitoring Streaming Slave Lag Effectively) na temat monitoringu replikacji, a dokładniej sprawdzania opóźnienia serwera standby w stosunku do primary. Autor przedstawił w nim funkcję zwracającą w prosty sposób informację o slave podłączonym i jego opóźnieniu. Kod funkcji (musi być stworzona i uruchamiana przez superusera bo dane o które pytamy dotyczą nie tylko naszej sesji i użytkownika):

CREATE OR REPLACE FUNCTION streaming_slave_check() RETURNS TABLE (client_hostname text, client_addr inet, byte_lag float)
LANGUAGE SQL SECURITY DEFINER
AS $$
    SELECT
        client_hostname,
        client_addr,
        sent_offset - (replay_offset - (sent_xlog - replay_xlog) * 255 * 16 ^ 6 ) AS byte_lag
    FROM (
        SELECT
            client_hostname,
            client_addr,
            ('x' || lpad(split_part(sent_location,   '/', 1), 8, '0'))::bit(32)::bigint AS sent_xlog,
            ('x' || lpad(split_part(replay_location, '/', 1), 8, '0'))::bit(32)::bigint AS replay_xlog,
            ('x' || lpad(split_part(sent_location,   '/', 2), 8, '0'))::bit(32)::bigint AS sent_offset,
            ('x' || lpad(split_part(replay_location, '/', 2), 8, '0'))::bit(32)::bigint AS replay_offset
        FROM pg_stat_replication
    ) AS s; 
$$;

A to jego przykładowy wynik uruchomienia:

postgres=# select * from streaming_slave_check();
 client_hostname |   client_addr   | byte_lag 
-----------------+-----------------+----------
                 | HOST-A          |        0
(1 row)

Mam nadzieję, że ten krótki post będzie dobrym wstępem do dalszych prac nad replikacją w PostgreSQLu. Miłej zabawy.



5 komentarzy:

  1. Sprawdzanie opóźnienia to jedno, a jak sprawdzić spójność baz danych?

    OdpowiedzUsuń
  2. A co gdy padnie master? Sprawdziłem taką sytuację. Wyłączyłem mastera i przełączyłem aplikację na slave, niestety slave jest w read-only. A jak zrobić aby można było w razie awarii korzystać ze slave?

    OdpowiedzUsuń
    Odpowiedzi
    1. A no racja, troszkę brakuje takiej informacji w poście. Dzięki za zwrócenie mi uwagi.

      Do pliku recovery.conf dodajamy nową linię:
      trigger_file = '/path/trigger_file_name'

      W momencie gdy chcesz promować slave na mastera trigerujesz go manualnie przez:

      touch /path/trigger_file_name

      Slave przechodzi z recovery mode na normal mode, a plik recovery.conf jest zmiany na recovery,done.

      Jak tylko będę miała chwilkę, to opiszę ten proces w nowym poście.

      Usuń
    2. Nowy post o promowaniu standby po awarii primary: http://db-diary.blogspot.com/2014/09/promowanie-serwera-standby-po-awarii.html

      Usuń
  3. Bet365: Best Bets & Online Review in India
    Bet365, one of the leading sports betting brands in the world, is sbobet ทางเข้า known for its incredible sports betting experience. 10bet As well as having a huge range of  Rating: 7.2/10 · ‎Review by TopBettingSites.com bet365

    OdpowiedzUsuń