Потоковая репликация и непрерывное архивирование базы данных PostgreSQL — делюсь небольшим опытом

Постарался кратко описать опыт настройки потоковой репликации и непрерывного архивирования в PostgreSQL.

Получил "в наследство" систему, в которой в качестве СУБД используется PostgreSQL на CentOS. Резервное копирование реализовано с помощью PostgreSQL Backup, которая запускает ночью задание, делает бекап двух баз и отправляет на ftp.

Решил заморочиться отказоустойчивостью.

Просто опишу вкратце что и в какой последовательности делалось по результатам изучения интернета и документации (спасибо postgrespro.ru), то есть не буду тут выкладывать много теории о том как работает PostgreSQL, что такое WAL файлы и т.д.
 

0. УСТАНОВКА PostgreSQL
инструкция по установке PostgreSQL:

команды после # выполняются в системной консоли от пользователя root,
команды после postgres=# — в консоли СУБД от пользователя postgres.

Установить репозиторий и пакеты из него:
# sudo rpm -ivh http://1c.postgrespro.ru/keys/postgrespro-1c-centos96.noarch.rpm && sudo yum makecache && sudo  yum install postgresql-pro-1c-9.6

Установить системную локаль в ru_RU.utf8:
# localectl set-locale LANG=ru_RU.utf8

Инициализировать кластер СУБД:
# service postgresql-9.6 initdb

Для подключения к базе по сети:
редактируем /var/lib/pgsql/9.6/data/pg_hba.conf :

(если не знаете как редактировать файл, то проще всего установить, если не установлена, программу похожую на far: # yum -y install mc и запустите # mc)

Закомментировать строку
host all all 0.0.0.0/0 ident
Добавить строку
host all all <client host ip> md5
где <client host ip> заменить на адрес машины (или подсети), из которой будете подключаться (ip сервера 1С Предприятие 8). Обязательно с маской
подсети, например: 192.168.1.11/32.

Запустить базу:
# service postgresql-9.6 start
 

Задать пароль пользователю СУБД postgres:
# sudo -u postgres psql
postgres=# alter user postgres password ‘yoursecretpassword’;q

                                   

Разрешить на фаерволе подключения к СУБД:
# firewall-cmd —zone=public —add-port=5432/tcp —permanent ; firewall-cmd —reload

Теперь сервер базы данных доступен, можно на сервере 1С предприятия создавать базы и т.д.

 

1. ПОТОКОВАЯ РЕПЛИКАЦИЯ
 

Итак, теперь у нас есть работающая (боевая) СУБД PstgreSQL. Назовем ее MASTER, а сервер, на который будем реплицировать базу SLAVE.

 

Для обеспечения работы потоковой репликации на MASTER-е редактируем файл /var/lib/pgsql/9.6/data/postgresql.conf, добавляем следующие строки:

wal_level = hot_standby (прочитайте про этот параметр в интернете и про WAL файлы в принципе)

max_wal_senders = 4 (количество планируемых слейвов, число 4 — на всякий случай )

max_replication_slots = 4 ( здесь 4 — это количество replication slot’ов — равен максимальному количеству реплик)

hot_standby = on (разрешить запросы на реплике)

hot_standby_feedback = on  (Определяет, будет ли сервер горячего резерва сообщать ведущему или вышестоящему резервному о запросах, которые он выполняет в данный момент)

Параметры hot_standby = on и hot_standby_feedback = on на MASTER-е не играют никакой роли, но мы их определим уже сейчас, так как на одном из следующих этапов при выстраивании потоковой репликации мы скопируем по сути вес data  каталог с MASTER-а на SLAVE, в том числе и этот конфигурационный файл, так что установим эти параметры уже сейчас.

 

На MASTER-е создаем пользователя repluser под которым SLAVE будет подключаться к MASTER-у и таскать WAL из слотов репликации.

# sudo -u postgres psql

postgres=# CREATE ROLE repluser WITH REPLICATION PASSWORD ‘супер-секретный-пароль’ LOGIN;q

 

На MASTER-е редактируем /var/lib/pgsql/9.6/data/pg_hba.conf, то есть, обеспечиваем, чтобы в этом файле были такие строчки

host    all             all             <ip_MASTER>/32        md5  
host    all             all             <ip_SLAVE>/32        md5  
host    all             all             <ip_Сервера1С>/32        md5 (эта строчка уже есть, создана на этапе 0.)
host    replication     repluser        <ip_MASTER>/32       md5 
host    replication     repluser        <ip_SLAVE>/32       md5 (разрешаем SLAVE-у подключаться к MASTER-у под пользователем repluser для осуществления потоковой репликации)

По сути, выше описанными разрешениями в файле pg_hba.conf мы разрешаем MASTER-у и SLAVE-у взаимно обращаться друг к другу, поэтому, как и в случае с файлом postgresql.conf, файл pg_hba.conf на обоих серверах может совпадать. Соответственно, в дальнейшем, при необходимости, MASTER может стать SLAVE-ом.

рестарт базы
# service postgresql-9.6 stop
# service postgresql-9.6 start

или 
# service postgresql-9.6 restart

 

ПЕРЕХОДИМ на SLAVE

Выполняем все что в пункте 0. УСТАНОВКА PostgreSQL

Останавливаем базу
# service postgresql-9.6 stop

Удаляем все файлы в директории data:
# rm -rf /var/lib/pgsql/9.6/data/*

Копируем с MASTER-а базу (обратите внимание — запускаем pg_basebackup под пользователем postgres, под которым работает база)
# sudo -u postgres pg_basebackup —host=<ip_MASTER> —username=repluser —pgdata=/var/lib/pgsql/9.6/data —xlog-method=stream —write-recovery-conf

выше написанная команда делает следующее — подключается к MASTER-у под пользователем repluser (команда затребует пароль, его нужно ввести, скорей всего можно в команде этот пароль и прописать, но я не заморачивался), копирует целиком базу вместе с конфигурационными файлами, а так же создает минимально необходимый файл recovery.conf, в котором собственно прописано, что база работает в режиме реплики, а значит пока существует этот файл, то в режиме только для чтения!

Привожу текст файла recovery.conf:
standby_mode = ‘on’
primary_conninfo = ‘user=repluser password=супер-секретный-пароль host=ip_MASTER port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres’

Как я уже говорил выше, если остановить базу, и переименовать файл recovery.conf, и снова запустить, то база перестает быть репликой.

Запускаем базу
# service postgresql-9.6 start

все :), SLAVE в теперь реплика, и регулярно таскает печеньки данные с MASTER-а

Что можно добавить?

Эта репликация асинхронная. Есть возможность настройки синхронной потоковой репликации. А так же каскадной, а так же и т.д. и т.д. Читайте, изучайте.

Все что сделано выше решит ситуацию, когда у вас внезапно взрывается MASTER — у вас есть актуальная копия, реплика. 

Примерный сценарий таков:
— останавливается SLAVE
— переименовывается recovery.conf
— запускается SLAVE
— на сервере 1С базы переподключаются к SLAVE-у, пользователи начинают работать, а вы решаете — что там случилось с MASTER-ом.

 

2. НЕПРЕРЫВНОЕ АРХИВИРОВАНИЕ

Предположим MASTER не взорвался, а просто кто-то умный запустил обработку, которая перепилила и перекорежила данные и все это торжественно перелетело в реплику на  SLAVE (см. все что написано выше).

Решает организация непрерывного архивирования.

Обязательно прочитайте (спасибо postgrespro.ru):
https://postgrespro.ru/docs/postgresql/9.6/continuous-archiving

чтобы иметь представление о том что такое WAL, файлы-сегменты WAL и т.д.

Вкратце схема следующая: 
— настраиваем непрерывное копирование WAL файлов
— делаем базовую резервную копию, после чего возникает возможность восстановить базу данных на любую временную точку после созданной базовой копии просто "накатывая" необходимое количество WAL файлов. Если базовая резервная копия сделана достаточно давно, то вам придется дольше по времени восстанавливать, накатывая большее количество файлов. Соответственно базовые резервные копии делайте чаще. Старые WAL файлы (созданные до "контрольной точки" сформированной очередной базовой резервной копии) можно "подчищать".

Опишу простейшую систему, когда архивируем на тот же дисковый массив, где и находится собственно база (что неправильно и вы конечно настройте копирование на другой диск, сервер, ftp и т.д.).

На MASTER-е редактируем /var/lib/pgsql/9.6/data/pg_hba.conf, добавляем следующую строчку (или убеждаемся что она уже есть):
local    replication    all        trust
 

Создаем папку archive, в которую будем копировать WAL файлы (обратите внимание — выполняем mkdir под пользователем postgres, чтобы установились нужные права на папку, и база был к ней доступ) 
# sudo -u postgres mkdir -p /var/lib/pgsql/9.6/backups/archive

Редактируем файл /var/lib/pgsql/9.6/data/postgresql.conf
archive_command = ‘test ! -f /var/lib/pgsql/9.6/backups/archive/%f && cp %p /var/lib/pgsql/9.6/backups/archive/%f’

(

то есть, задаем желаемую команду оболочки в параметре archive_command. В archive_command символы %p заменяются полным путём к файлу, подлежащему архивации, а %f заменяются только именем файла. Поэтому когда WAL файл готов к копированию (заполнен) вызывается примерно следующая команда:
test ! -f /var/lib/pgsql/9.6/backups/archive/00000001000000A900000065 && cp pg_xlog/00000001000000A900000065 /var/lib/pgsql/9.6/backups/archive/00000001000000A900000065

)

# service postgresql-9.6 restart

Создаем папку basebackups, в которую положим заархивированную базовую резервную копию (обратите внимание — выполняем mkdir под пользователем postgres, чтобы установились нужные права на папку, и база был к ней доступ) 
# sudo -u postgres mkdir -p /var/lib/pgsql/9.6/backups/basebackups

Делаем базовую резервную копию:
# pg_basebackup -U postgres -D /var/lib/pgsql/9.6/backups/basebackups -Ft -z -Xf -Pv

здесь делаем базовую резервную копию и архивируем все в один файл (в моем случае образовался файл с именем base.tar.gz).  В общем изучите возможности pg_basebackup.
Если бы каталог basebackups был не пустой pg_basebackup, то выдаст ошибку:
pg_basebackup: каталог "/var/lib/pgsql/9.6/backups/basebackups" существует, но он не пуст
Поэтому, последующие базовые резервные копии я буду делать так:
# pg_basebackup -U postgres -D /var/lib/pgsql/9.6/backups/basebackups/имя_нового_каталога -Ft -z -Xf
(pg_basebackup сам создаст этот каталог, предварительно его создавать не нужно).

Кстати, по результатам работы pg_basebackup в папке, куда мы копируем WAL файлы, мы увидим подобный файл.

-rw——- 1 postgres postgres      308 окт 24 02:37 00000001000000150000006B.00000028.backup
по сути — это временная метка с которой можно восстанавливать базу из архива.

К сожалению процесс восстановления описать не могу, так как мне еще предстоит его протестировать, обкатать. Надеюсь найти время и дописать статью.

P.S. это моя первая статья, не судите строго

9 Comments

  1. Трактор

    Толковая статья. Наши админы остановились только на первой части. Сделали репликацию. Подскажу, чтобы ещё и непрерывное резервирование сделали.

    Reply
  2. awk

    Плюсанул, а Mightnight commander похожий на FAR улыбнуло…

    Reply
  3. KRIHA

    (2) ))) ну а что — я с линуксом только начал работать. вот к примеру — подчищать архивные WAL файлы — пытался сгенерить команду, которая бы удаляла файлы, созданные ранее определенной даты-времени.. в общем забил, открыл MC и инсёртом выделил все что надо и F8 ))))))))))

    Reply
  4. awk

    (3) Тут линукс не причем. до фара и мс был командир Нортон.

    Reply
  5. KRIHA

    (4) ааааааааа, об этом ))))))))

    Reply
  6. viptextil

    (3)

    …команду, которая бы удаляла файлы, созданные ранее определенной даты-времени…

    find /PathToFiles -type f -mtime +3 -exec rm {} ;

    Удаляет файлы, созданные более трех дней назад.

    Reply
  7. KRIHA

    (6) Виктор, спасибо. Но я имел ввиду следующее — есть четкая граница по дата-времени — например 2017-11-02 02:00:00. Я хочу вбить в команду эту отметку и команда удаляет все что созданное ранее. А так — получается — нужно вашу команду запустить ровно в два часа ночи 5-го ноября. Я утрирую конечно :)).

    Reply
  8. viptextil

    (7) То, о чем Вы просите — ручной режим. Автоматизация предполагает выполнение определенных действий регулярно.

    Если требуется очистка именно в 02:00:00, то cron это позволяет. В нем есть очень гибкие настройки. Если тонкости настроек не хватает, важно помнить, что с помощью cron, запускаются скрипты, уж там всяких условий понапихать можно.

    Reply
  9. KRIHA

    (8) да, тут есть о чем подумать. Если я правильно понял, вы говорите об автоматизации процесса создания новой базовой резервной копии в связке с удалением «лишних» WAL файлов, сформированных до нее (новой базовой резервной копии). Тогда да — загоняем все в скрипт и т.д. Пока знаний для этого у меня не достаточно.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *