Не так давно на рабочем проекте была поставлена задача настроить механизм репликации данных из основной базы PostgreSQL в базу PipelineDB.
В этой статье я изложу ход решения данной задачи.
PipelineDB - одна из реализаций ныне набирающих популярность стриминговых СУБД. О преимуществах стриминговых СУБД в различных кейсах (https://www.pipelinedb.com/use-cases) вы можете без труда прочитать сегодня на множестве ресурсов. Очень просто принцип их работы визуализирован на сайте www.pipelinedb.com в разделе “How It Works”.
PipelineDB это форк PostgreSQL с дополнительной функциональностью, позволяющей хранить только агрегированные данные, рассчитывая дельту из поступающего стрима (отсюда и название этого типа СУБД) на лету. Эти данные хранятся в специальных объектах PipelineDB, называемых continuous views. Сам же стрим в простейшем случае получается из обычных таблиц, хранимых в этой же БД.
Рассмотрим кейс, в котором:
- на продуктовой среде у нас уже работает СУБД PostgreSQL версии 9.4+,
- нам нужно получить ее read-only реплику.
Read-only реплика необходима для того, что-бы разгрузить основную базу от множественных и тяжелых SELECT-запросов которые генерируют многочисленные внутренние сервисы аналитики.
Первое решение, которое приходит в голову: замечательный встроенных механизм потоковой асинхронной репликации PostgreSQL, который появился в версии 9.0 (http://peter.eisentraut.org/blog/2015/03/03/the-history-of-replication-in-postgresql/). Но практически сразу стало ясно, что этот механиз репликации мне не подходит в силу своих ограничений в рамках поставленой задачи:
- мастер и реплика должны иметь одинаковую мажорную версию PostgreSQL, а по возможности и крутиться на идентичном “железе”,
- реплика при этом работает в режиме “hot standby”, в котором она доступна только для чтения.
В моем случае первое ограничение помешало мне поднять реплику мастер-сервера, работающего под управлением Postgre 9.6, т.к. версия этой СУБД, используемая как базовая для последней версии PipelineDB - только 9.5. Если у Вас мастер работает под управлением Postgre 9.5, то вы можете попробовать такой фокус, но скорее всего мастер просто не распознает PipelineDB как полноценный и равный себе PostgreSQL.
Второе ограничение оказалось значительно более существенным. Как я писал в начале, PipelineDB хранит в базе свои метаданные для обслуживания этих самых continuous views, ради которых все и затевается. Но согласно принципам работы стриминговой репликации - реплика должна выглядеть один-в-один с мастером: реплика существует в формате read-only и исключает любые возможные различия с мастером. В моем случае это было не допустимо.
Стриминговая репликация мне не подошла, поэтому очевидный вывод: нужно смотреть в сторону логической репликации. И тут открывается целый океан возможностей.
При первом ознакомлении с перечнем различных инструментов для реализации процесса логической репликации и разнообразием методик первое желание, которое возникает, это... сменить вид деятельности. Но первый шок проходит, и мы начинаем вылавливать из этого океана достойных кандидатов на пост инструмента нашей мечты.
Среди популярных инструментов:
- slony (trigger-based),
- pgpool / pgpool-II (middleware).
Мой выбор пал на slony.
Две недели работы над конфигурацией slony для моего случая успехом так и не увенчалась. Упрощая конфигурацию среды и сводя количество внешних факторов к минимуму настроить slony не удавалось.
В конце-концов изначальный эксперимент по репликации упростился до следующих исходных условий:
- мастер и слейв были запущены в docker-контейнерах (хост система – macOS),
- образы для контейнеров содержали Alpine Linux с PostgreSQL 9.6.
Но даже в этом случае демон slony упорно не хотел запускаться, падая с ошибкой Segmentation fault
. Не исключено что мои исходные условия в том или ином смысле были несовместимы со Slony, и в другой системной конфигурации у вас наверняка все получится.
Впрочем после прочтения статьи дальше вы можете не захотеть колупаться в этой древней утилите. Не стоит забывать и об этом: http://howfuckedismydatabase.com/postgres/slony.php
До pgpool / pgpool-II я так и не добрался, потому что по дороге нашел то, что и стало в конечном итоге решением: утилита pglogical от 2ndQuadrant (https://2ndquadrant.com/en/resources/pglogical/), которая вообще не использует никаких триггеров, а подключается к СУБД в качестве плагина.
Чтение документации по утилите и осознание кто же такие 2ndQuadrant сразу расположило меня к этому решению. Главным разработчиком pglogical является человек по имени Petr Jelinek, активный контрибутор PostgreSQL. Он реализовал логическую репликацию из коробки (а так-же ряд ее улучшений, см. 1 и 2, которая будет доступна с выходом версии PostgreSQL предположительно в 3м квартале 2017 года.
Похоже что pglogical явился своеобразным успешным proof-of-concept-ом, и одновременно единственным стабильным решением логической репликации для версий PostgreSQL 9.4+.
В свете вышеизложенного стоит ли говорить что я принял решение подвинуть pgpool
в пользу pglogical
?
Тем не менее практически сразу меня ждал неприятный сюрприз. В эта утилита существует только для PostgreSQL версий 9.4, 9.5 и 9.6. Официальной поддержкой PipelineDB и не пахло: утилита наотрез отказалась устанавливаться на хост с PipelineDB, радостно сообщая:
unmet dependency postgresql-9.5
Казалось что замечательный эксперимент закончился так по сути и не начавшись.
Но смутное подозрение того, что PipelineDB это все тот же самый PostgreSQL - структура каталогов базы, конфигурационных файлов, встроенных команд и сервисных утилит это наглядно доказывала - меня не покидало. И я решился на небольшую хитрость.
На хост с PipelineDB утилита pglogical
устанавливается следующим образом (все делалось в docker-контейнере под рутом):
- Добавляем репозиторий и скачиваем пакеты утилиты:
echo "deb [arch=amd64] http://packages.2ndquadrant.com/pglogical/apt/ jessie-2ndquadrant main" > /etc/apt/sources.list.d/2ndquadrant.list
wget --quiet -O - http://packages.2ndquadrant.com/pglogical/apt/AA7A6805.asc | apt-key add -
apt-get update && apt-get download libpq5 postgresql-9.5-pglogical
- Устанавливаем необходимые библиотеки и сам пакет с игнорированием зависимостей, решая нашу проблему нежелания утилиты устанавливаться на что либо кроме PostgreSQL:
dpkg -i --ignore-depends=postgresql-9.5 libpq5_9.4.10-0+deb8u1_amd64.deb
dpkg -i --ignore-depends=postgresql-9.5 postgresql-9.5-pglogical_1.2.2-1jessie_amd64.deb
- Удаляем запись о зависимости из файла
/var/lib/dpkg/status
, чтобы при дальнейшей работеapt-get
она не ругалась на ненайденную зависимость и не предлагала нам удалитьpglogical
:
sed 's/, postgresql-9.5//g' /var/lib/dpkg/status > /var/lib/dpkg/status-new && \
mv /var/lib/dpkg/status /var/lib/dpkg/status.bkp && \
mv /var/lib/dpkg/status-new /var/lib/dpkg/status
- Утилита установлена на хост с PipelineDB.
Но вот снова незадача - утилита устанавливается в папки с именами PostgreSQL, а PipelineDB имеет аналогичную структуру папок, но с именами PipelineDB. Ну так не будем по этому поводу унывать и переместим файлы утилиты в соответствующие папки уже PipelineDB:
mv /usr/lib/postgresql/9.5/lib/* /usr/lib/pipelinedb/lib/pipelinedb/
mv /usr/lib/postgresql/9.5/bin/* /usr/lib/pipelinedb/bin/
mv /usr/share/postgresql/9.5/extension/* /usr/lib/pipelinedb/share/pipelinedb/extension/
Все!
Получлся готовый к использованию работающий сервер с PipelineDB с установленной утилитой pglogical
.
После непродолжительной настройки кластера мастер-слейв (PostgreSQL-PipilineDB), описание которой можно найти на миллионе ресурсов, включая документацию PostgreSQL, а так-же после прохождения простеньких шагов настройки самой утилиты (https://2ndquadrant.com/en/resources/pglogical/pglogical-docs/) мы можем убедиться, что репликация работает.
Буду рад услышать замечания по сути и предложения по повествованию. Самые лучшие предложения будут реализованы в виде правок к статье.