
Настройка мастера для потоковой репликации
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Изменяем параметры.

    psql -h localhost -p 5432 -U postgres

    => alter system set wal_level = hot_standby;
    ALTER SYSTEM

    => alter system set archive_mode = off;
    ALTER SYSTEM

    => alter system set max_standby_streaming_delay = '10s';
    ALTER SYSTEM

    => alter system set max_replication_slots = 5;
    ALTER SYSTEM

    => alter system set max_wal_senders = 5;
    ALTER SYSTEM

    => alter system set port = 5432;
    ALTER SYSTEM

    => alter system set hot_standby = off;
    ALTER SYSTEM

    => alter system set hot_standby_feedback = off;
    ALTER SYSTEM

    => alter system set wal_receiver_status_interval = 0;
    ALTER SYSTEM

Файл pg_hba.conf должен содержать строку для базы данных replication:

postgres> sed -i s/#\(\w\+\s\+replication\)/\1/ /usr/local/pgsql/data/pg_hba.conf 



postgres> tail -n 5 /usr/local/pgsql/data/pg_hba.conf 
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     postgres                                trust
host    replication     postgres        127.0.0.1/32            trust
host    replication     postgres        ::1/128                 trust

Перезапустим сервер.

    => \q

postgres> pg_ctl restart -w -l /home/postgres/logfile 
waiting for server to shut down.... done
server stopped
waiting for server to start.... done
server started

Слот репликации.

    psql -h localhost -p 5432 -U postgres

    => select pg_create_physical_replication_slot('slot_a');
     pg_create_physical_replication_slot 
    -------------------------------------
     (slot_a,)
    (1 row)
    


Создание и настройка первой реплики
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


postgres2> bash -c "rm -rf /usr/local/pgsql2/data/*" 
postgres2> pg_basebackup -U postgres -p 5432 -D /usr/local/pgsql2/data -X stream -R 

Изменение файла postgresql.auto.conf:

postgres2> sed -i "s/port = .*/port = 5433/" /usr/local/pgsql2/data/postgresql.auto.conf 
postgres2> sed -i "s/hot_standby = .*/hot_standby = on/" /usr/local/pgsql2/data/postgresql.auto.conf 
postgres2> sed -i "s/hot_standby_feedback = .*/hot_standby_feedback = on/" /usr/local/pgsql2/data/postgresql.auto.conf 
postgres2> sed -i "s/wal_receiver_status_interval = .*/wal_receiver_status_interval = 1s/" /usr/local/pgsql2/data/postgresql.auto.conf 



postgres2> cat /usr/local/pgsql2/data/postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
wal_level = 'hot_standby'
archive_mode = 'off'
max_standby_streaming_delay = '10s'
max_replication_slots = '5'
max_wal_senders = '5'
port = 5433
hot_standby = on
hot_standby_feedback = on
wal_receiver_status_interval = 1s

Добавляем слот репликации в recovery.conf.


postgres2> bash -c "echo primary_slot_name = \\'\'slot_a\\'\' >> /usr/local/pgsql2/data/recovery.conf" 



postgres2> cat /usr/local/pgsql2/data/recovery.conf 
standby_mode = 'on'
primary_conninfo = 'user=postgres port=5432 sslmode=disable sslcompression=1'
primary_slot_name = 'slot_a'


Запуск первой реплики и проверка
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


postgres2> pg_ctl start -w -l /home/postgres2/logfile 
waiting for server to start..... done
server started

    => create database db13;
    CREATE DATABASE

    => \c db13
    You are now connected to database "db13" as user "postgres".

    => create table replica_test(t text);
    CREATE TABLE

    => create function test() returns integer as $$ select pg_sleep(1); select count(*)::integer from replica_test;$$ language sql;
    CREATE FUNCTION

    |    psql -h localhost -p 5433 -U postgres

    |    => \c db13
    |    You are now connected to database "db13" as user "postgres".

    |    => select * from replica_test;
    |     t 
    |    ---
    |    (0 rows)
    |    

Репликация работает.

Создаем слот репликации (реплика допускает эту операцию):

    |    => select pg_create_physical_replication_slot('slot_a');
    |     pg_create_physical_replication_slot 
    |    -------------------------------------
    |     (slot_a,)
    |    (1 row)
    |    


Создание и настройка второй реплики
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Для второй реплики используем резервную копию, сделанную с первой реплики -
чтобы заодно продемонстрировать возможность делать резервные копии не на мастере.

postgres3> bash -c "rm -rf /usr/local/pgsql3/data/*" 
postgres3> pg_basebackup -U postgres -p 5433 -D /usr/local/pgsql3/data -X stream -R 

Изменение файла postgresql.auto.conf:

postgres3> sed -i "s/port = .*/port = 5434/" /usr/local/pgsql3/data/postgresql.auto.conf 
postgres3> sed -i "s/hot_standby = .*/hot_standby = on/" /usr/local/pgsql3/data/postgresql.auto.conf 
postgres3> sed -i "s/hot_standby_feedback = .*/hot_standby_feedback = on/" /usr/local/pgsql3/data/postgresql.auto.conf 
postgres3> sed -i "s/wal_receiver_status_interval = .*/wal_receiver_status_interval = 1s/" /usr/local/pgsql3/data/postgresql.auto.conf 



postgres3> cat /usr/local/pgsql3/data/postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
wal_level = 'hot_standby'
archive_mode = 'off'
max_standby_streaming_delay = '10s'
max_replication_slots = '5'
max_wal_senders = '5'
port = 5434
hot_standby = on
hot_standby_feedback = on
wal_receiver_status_interval = 1s

Добавляем слот репликации и задержку применения в recovery.conf.

postgres3> bash -c "echo primary_slot_name = \\'\'slot_a\\'\' >> /usr/local/pgsql3/data/recovery.conf" 
postgres3> bash -c "echo recovery_min_apply_delay = \\'\'10s\\'\' >> /usr/local/pgsql3/data/recovery.conf" 

Еще один важный шаг: надо установить параметр recovery_target_timeline в значение latest.
Иначе, когда первая реплика будет повышена до мастера и увеличит номер ветви времени,
вторая реплика продолжит чтение данных прежней ветви времени - то есть по сути репликация остановится

postgres3> bash -c "echo recovery_target_timeline = \\'\'latest\\'\' >> /usr/local/pgsql3/data/recovery.conf" 



postgres3> cat /usr/local/pgsql3/data/recovery.conf 
standby_mode = 'on'
primary_conninfo = 'user=postgres port=5433 sslmode=disable sslcompression=1'
primary_slot_name = 'slot_a'
recovery_min_apply_delay = '10s'
recovery_target_timeline = 'latest'


Запуск второй реплики и проверка
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


postgres3> pg_ctl start -w -l /home/postgres3/logfile 
waiting for server to start...... done
server started

    => insert into replica_test values ('Проверка связи');
    INSERT 0 1

    ||        psql -h localhost -p 5434 -U postgres

    ||        => \c db13
    ||        You are now connected to database "db13" as user "postgres".

    ||        => select 'After '||i||' sec', test() from generate_series(1,15) as gen(i);
    ||           ?column?   | test 
    ||        --------------+------
    ||         After 1 sec  |    0
    ||         After 2 sec  |    0
    ||         After 3 sec  |    0
    ||         After 4 sec  |    0
    ||         After 5 sec  |    0
    ||         After 6 sec  |    0
    ||         After 7 sec  |    0
    ||         After 8 sec  |    0
    ||         After 9 sec  |    0
    ||         After 10 sec |    1
    ||         After 11 sec |    1
    ||         After 12 sec |    1
    ||         After 13 sec |    1
    ||         After 14 sec |    1
    ||         After 15 sec |    1
    ||        (15 rows)
    ||        

Репликация с задержкой работает.

Останов мастера и повышение первой реплики
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    => \q

postgres> pg_ctl stop -m immediate 
waiting for server to shut down... done
server stopped
postgres2> pg_ctl -w promote 
server promoting


Проверка второй реплики
~~~~~~~~~~~~~~~~~~~~~~~


    |    => insert into replica_test values ('Проверка связи - 2');
    |    INSERT 0 1

    ||        => select 'After '||i||' sec', test() from generate_series(1,15) as gen(i);
    ||           ?column?   | test 
    ||        --------------+------
    ||         After 1 sec  |    1
    ||         After 2 sec  |    1
    ||         After 3 sec  |    1
    ||         After 4 sec  |    1
    ||         After 5 sec  |    1
    ||         After 6 sec  |    1
    ||         After 7 sec  |    1
    ||         After 8 sec  |    1
    ||         After 9 sec  |    1
    ||         After 10 sec |    2
    ||         After 11 sec |    2
    ||         After 12 sec |    2
    ||         After 13 sec |    2
    ||         After 14 sec |    2
    ||         After 15 sec |    2
    ||        (15 rows)
    ||        

Репликация продолжает работать.


Возвращаем все обратно: останавливаем реплики, запускаем мастер.

    |    => \q

postgres2> pg_ctl stop -D /usr/local/pgsql2/data 
waiting for server to shut down.... done
server stopped

    ||        => \q

postgres3> pg_ctl stop -D /usr/local/pgsql3/data 
waiting for server to shut down.... done
server stopped
postgres> pg_ctl -w start -l /home/postgres/logfile 
waiting for server to start..... done
server started
    psql -h localhost -p 5432 -U postgres

    => select pg_drop_replication_slot('slot_a');
     pg_drop_replication_slot 
    --------------------------
     
    (1 row)
    

    => alter system reset all;
    ALTER SYSTEM

    => \q

postgres> pg_ctl restart -w -l /home/postgres/logfile 
waiting for server to shut down.... done
server stopped
waiting for server to start.... done
server started
