Главная
Главная Руководства PostgreSQL › Потоковая репликация master-slave в postgresql.



Автор:

Статья опубликована: 2019-04-11 12:14:11
Последние правки: 2019-04-11 18:28:21

Postgresql располагает встроенными средствами для создания серверов горячего резервирования. Это потоковая репликация с master на один или несколько slave. В данном мануале рассматривается только настройка репликации. Тестирование проводилось на postgresql 9.5.

  • Исходные данные
    ~# cat /etc/os-release
    Ubuntu 16.04.6 LTS
    

  • master

    postgresql.conf
    wal_level = hot_standby     # для PostgreSQL < 9.6 
    #wal_level = replica        # для PostgreSQL >= 9.6
    
    # максимально допустимое число одновременных подключений
    # клиентов потокового копирования. По умолчанию это
    # значение равно нулю, то есть репликация отключается.
    # Этот параметр не может превышать max_connections.
    max_wal_senders = 3
    
    # Задаёт минимальное число файлов прошлых сегментов журнала, которые будут 
    # сохраняться в каталоге pg_xlog, чтобы резервный сервер мог выбрать их при
    # потоковой репликации.
    wal_keep_segments = 128
    
    pg_hba.conf
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    host    replication     postgresql     192.168.0.0/24           trust
    
    Мы разрешили подключение без пароля (trust) для репликации под пользователем postgresql из подести 192.168.0.0/24. Тру-одмины считают, что так делать нехорошо, а потому для большей секьюрности рекомендуют создать отдельную роль (пользователя) с паролем:
    # su postgres
    $ psql
    postgres=# CREATE ROLE replicator WITH REPLICATION PASSWORD 'REPPASSWORD' LOGIN;
    
    В этом случае запись в pg_hba.conf должна выглядеть так:
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    host    replication     replicator     192.168.0.0/24           md5
    
    Далее необходимо перезагрузить postgresql, после чего настройка мастера считается завершенной:
    $ sudo systemctl restart postgresql@9.5-main
    $ sudo systemctl status postgresql@9.5-main
    

  • slave

    Останавливаем:
    $ sudo systemctl stop postgresql@9.5-main
    
    postgresql.conf
    # Определяет, можно ли будет подключаться к серверу и выполнять
    # запросы в процессе восстановления.Данный параметр играет роль
    # только в режиме резервного сервера или при восстановлении архива.
    hot_standby = on
    
    Удаляем всё, что есть внутри /var/lib/postgresql/9.5/main.
    $ sudo rm -Rf /var/lib/postgresql/9.5/main/*
    
    Копируем текущее состояние master (ip=192.168.0.1):
    Вариант для репликации под postgres без пароля:
    $ sudo -u postgres bash
    $ pg_basebackup -h 192.168.0.1 -U postgres -D /var/lib/postgresql/9.5/main -R --xlog-method=stream
    
    Вариант для репликации под replicator с паролем:
    $ sudo -u postgres bash
    $ pg_basebackup -h 192.168.0.1 -U replicator -D /var/lib/postgresql/9.5/main -R -P --xlog-method=stream
    
    В этом случае у вас спросят пароль пользователя replicator (вы его создавали на master-e)

    Дожидаемся окончания копирования баз, после чего смотрим содержимое файла /var/lib/postgresql/9.5/main/recovery.conf (он будет создан после завершения работы pg_basebackup). Ниже вариант для replicator с паролем:
    standby_mode = 'on'
    primary_conninfo = 'user=replicator password=REPPASSWORD host=192.168.0.1 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres'
    
    Что нам остается - это дописать в конец строку с переменной, в которой указан путь к файлу, существование которого говорит нашему slave что настал его час и теперь он - новый мастер:
    trigger_file = '/var/lib/postgresql/9.5/main/trigger_file'
    
    Не забываем, что файл /var/lib/postgresql/9.5/main/trigger_file нужно создавать только когда умер master!

    Запускаем postgresql:
    $ sudo systemctl start postgresql@9.5-main
    $ sudo systemctl status postgresql@9.5-main
    

  • Мониторинг состояния

    Проверяем, запущены ли процессы.
    На мастере:
    $ sudo ps ax | grep sender
    
    На слейве:
    $ sudo ps ax | grep receiver
    
    Выполняем sql-запрос на мастере:
    # sudo -u postgres psql -c 'SELECT *,pg_xlog_location_diff(s.sent_location,s.replay_location) byte_lag FROM pg_stat_replication s;'
     pid  | usesysid | usename  | application_name |  client_addr   | client_hostname |
    ------+----------+----------+------------------+----------------+-----------------+
     9771 |       10 | postgres | walreceiver      | 192.168.0.1    |                 |
    ...
     client_port |         backend_start         | backend_xmin |   state   |
    -------------+-------------------------------+--------------+-----------+
           53690 | 2019-04-11 16:39:12.566607+03 |              | streaming |
    ...
     sent_location | write_location | flush_location | replay_location |
    ---------------+----------------+----------------+-----------------+
     11B9/7647DF08 | 11B9/7647DF08  | 11B9/7647DF08  | 11B9/7647DF08   |
    ...
     sync_priority | sync_state | byte_lag 
    ---------------+------------+----------
                 0 | async      |       12
    (1 row)
    
    Строку ответа на запрос разбил на несколько, чтобы не уползала в закат.
    Колонка byte_lag показывает в байтах, на сколько слейв отстает от мастера;
    Для postgresql версий 10 и позже, запрос немного другой:
    # sudo -u postgres psql -c 'SELECT *,pg_wal_lsn_diff(s.sent_lsn,s.replay_lsn) AS byte_lag FROM pg_stat_replication s;'
    

    На слейве можно выполнить sql-запрос, с помощью которого узнать сколько времени прошло с момента последнего обновления данных с мастера:
    # sudo -u postgres psql -c "SELECT now()-pg_last_xact_replay_timestamp();"
        ?column?     
    -----------------
     00:00:03.773876
    (1 row)