В Яндекс.Деньгах хранится масса важной для комфортной работы пользователя информации. Настройки профилей и подписки на штрафы тоже нужно бэкапить, чем и занимается у нас связка из Barman Backup & Recovery for PostgreSQL и pg_receivexlog. В статье расскажу о том, почему архитектура стала такой, какой стала, а также расскажу, как реализовать подобный сценарий для вашей базы PostgreSQL. До описываемых в статье изменений бэкап платежной системы снимался с мастер-базы в одном из наших дата-центров (ДЦ). Вообще, платежная система состоит из множества отдельных сервисов, баз и приложений. Все это добро резервируется сообразно важности данных. Так как статья более практическая, рассмотрю в качестве примера одну из множества СУБД без повышенных требований к безопасности – в ней хранятся настройки пользовательских профилей, история переводов, предпочтения по аутентификации и прочее. Проблема резервного копирования только с активных узлов в том, что если мастер переключали на второй ДЦ (где резервных копий не было), то бэкап-сервер первого ДЦ медленно и долго собирал копии с нового мастера по сети. И потенциальные потери самых последних транзакций при восстановлении стали вызывать все больше опасений по мере роста числа пользователей. Итого, будем решать следующие задачи: Обеспечение доступности резервных копий при отказе ДЦ или бэкап-сервера. Масштаб нашей задачи составляли 20 серверов PostgreSQL 9.5 (10 мастеров и 10 слейвов), обслуживающих 36 баз данных суммарным объемом около 3 ТБ. Но описываемый сценарий подойдет и для пары серверов с критичными БД. Общая схема нового решения представлена ниже, она довольно незамысловата:
 По одному серверу резервного копирования в каждом ДЦ, конфигурация у них общая (один из плюсов Barman). Процесс конфигурации выглядит следующим образом: 1. Подключаемся к серверу БД и с помощью пакетного менеджера устанавливаем postgresql-9.5-pgespresso – расширение для интеграции Barman Backup & Recovery c PostgreSQL. Все команды приводятся для Ubuntu, для других дистрибутивов могут быть отличия: 2. Устанавливаем расширение pg_espresso в PostgreSQL: 3. Теперь на сервере с Barman нужно создать файл, описывающий настройки резервного копирования для сервера db1 – db1.conf в каталоге /etc/barman.d/ со следующим содержимым: 4. Далее нужно создать слот репликации, чтобы гарантировать, что мастер не удалит журналы транзакций, которые еще не были получены репликой: 5. И проверить, что Barman видит сервер и забирает с него журналы транзакций: Если все команды выполнены правильно, то в результате выполнения команды проверки должно получиться нечто похожее: Теперь Barman будет забирать журналы и делать бэкапы с реплик. В бэкап попадают все базы PostgreSQL c профилями пользователей, историей платежей, подписками на штрафы, настройками аутентификации и т.п. Напомню, что нулевое RPO при восстановлении нам очень важно, поэтому решили подстраховать Barman дополнительным механизмом – pg_receivexlog. Этот процесс находится на отдельном сервере – не на сервере с базой данных – и непрерывно переносит копии журналов транзакций из мастер-ноды в отдельное хранилище журналов транзакций, доступное для реплики. И так для каждого ДЦ отдельно.  Особенность механизма в том, что СУБД не подтвердит приложению запись данных в базу, пока не получит подтверждение от pg_receivexlog об успешном копировании транзакции. Без этого сохранялась бы вероятность следующего сценария: Допустим, Иннокентий платит 100 рублей за сотовую связь, операция успешно проводится нашей платежной системой (ПС). Сразу после проведения в бэкенде происходит авария, и мы откатываем бэкап, включая журналы транзакций.  Получается, что ПС знает о проведении платежа, деньги не потеряны, но саму операцию в истории не посмотреть. Конечно, это неудобно и обескураживает. Операцию пришлось бы в ручном режиме вносить через службу поддержки. Теперь как настроить чудо механизм синхронного переноса логов: 1. Создаем слот для сборщика логов: 2. Запускаем службы сбора логов с сервера PostgreSQL: 3. После запуска pg_receivexlog будет пытаться в синхронном режиме сохранять журналы транзакций в каталог. Таких сборщиков может быть несколько, по одному на сервер PostreSQL. Но чтобы синхронный режим заработал, нужно в настройках СУБД на мастер-ноде указать параметр в конфигурации PostgreSQL: 4. Но чтобы при отказе сервера со сборщиком логов мастер-нода могла продолжать обработку пользовательских транзакций, вторым сервером лучше указать реплику. На реплике в recovery.conf нужно указать, откуда брать журналы транзакций в случае недоступности мастер-ноды: Конечно, при выходе из строя сервера сбора логов скорость работы всей системы немного снизится, потому что вместо синхронной отправки журналов на сборщик логов в том же ДЦ, что и мастер, придется отправлять их с подтверждением в другой ДЦ. Тем не менее стабильность важнее. В качестве резюме приведу немного конкретики о времени и объеме бэкапов по описанной в статье схеме. Полный бэкап упомянутых серверов снимается в Яндекс.Деньгах ежедневно и весит около 2 ТБ, на обработку которых бэкап-серверу нужно 5-10 часов. Кроме того, выполняется постоянный бэкап журналов транзакций с помощью перемещения их файлов в хранилище. Реактивист-разработчик Android