[Из песочницы] Настройка репликации между PostgreSQL и PipelineDB
Конкретно PipelineDB это форк PostgreSQL с дополнительной функциональностью, позволяющей хранить только агрегированные данные, рассчитывая дельту из поступающего стрима (отсюда и название этого типа СУБД) на лету. Эти данные хранятся в специальных объектах PipelineDB, называемых continuous views. Сам же стрим в простейшем случае формируется из обычных таблиц, хранимых в этой же БД.
Мы рассмотрим кейс, в котором на продуктовой среде у нас уже работает СУБД PostgreSQL версии 9.4+, а нам нужно получить ее read-only реплику для того, чтобы разгрузить основную базу от множественных и тяжелых SELECT-запросов, получаемых от, например, систем отчетности, DWH или наших витрин данных. И после изучения вопроса Вы можете решить, что именно стриминговая СУБД очень хорошо подходит для такой задачи.
Но вот незадача — какой же механизм репликации использовать? После дополнительного изучения вопроса мы приходим к выводу, что замечательный встроенный механизм потоковой асинхронной (физической) репликации PostgreSQL, который появился в PostgreSQL версии 9.0 и постоянно развивается, не подходит в силу своих ограничений, а именно:
а) мастер и реплика должны иметь одинаковую мажорную версию PostgreSQL, а по возможности и крутиться на идентичном «железе».
б) реплика при этом работает в режиме «hot standby», в котором она доступна только для чтения.
В моем случае первое ограничение помешало мне поднять на PipelineDB реплику мастер-сервера, работающего под управлением Postgre 9.6, т.к. версия этой СУБД, используемая как базовая для последней версии PipelineDB — только 9.5. Если у Вас мастер работает под управлением Postgre 9.5, то вы можете попробовать такой фокус, но есть большая вероятность, что мастер-сервер просто не распознает PipelineDB как полноценный и равный себе PostgreSQL — механизм асинхронной потоковой репликации очень капризный в этом плане.
Второе ограничение более существенное. Как мы уже выяснили, PipelineDB пишет в базу свои данные. Как минимум это continuous views, ради которых мы с нем и заморочились. Но второе ограничение разрешает нашей реплике быть только полной — один в один — копией базы мастера без возможности в нее писать. Что нас совершенно не устраивает.
Т.о., т.к. физическая репликация нам не подходит, мы понимаем, что нам нужно смотреть в сторону логической репликации. Не лишенной своих недостатков, но полностью устраняющей эти два ограничения, а именно:
а) логическая репликация позволяет делать реплику только тех данных, которые нам нужны, а не всех данных мастера один-в-один.
б) и логическая репликация не блокирует слейв на запись.
И тут перед нами открывается целый океан возможностей.
При первом ознакомлении с перечнем различных инструментов для создания логической репликации и разнообразием методик самой репликации первое желание, которое возникает, это желание сменить вид деятельности. Но первый шок проходит, и мы начинаем вылавливать из этого океана достойных кандидатов на пост инструмента нашей мечты.
Годная статья, в которой хорошо рассматриваются вопросы и репликации и обеспечивающих ее утилит в том числе: postgresql.leopard.in.ua/html/#репликация
Одни из самых популярных инструментов, используемых для этого это slony (trigger-based) и pgpool/pgpool-II (middleware).
Сразу скажу, что попытка решить эту задачу с помощью очень известной и популярной утилиты Slony версии 2.2.5 за две недели успехом так и не увенчалась — даже в случае когда для целей пруф-оф-концепт и мастер и реплика работали под управлением одинаковой версии PostgreSQL. Демон slony упорно не хотел запускаться и перезагружался сразу при запуске из-за segmentation fault, причину которого найти не удалось. Да и неблагодарное это дело искать причины segmentation faults в ПО сторонних поставщиков. Более того та же самая картина наблюдалась и при компиляции этой утилиты из исходных кодов и при установке ее из родного репозитория Alpine Linux.
Этот эксперимент проводился с такими отправными данными:
— docker-контейнеры
— postgre 9.6 на Alpine Linux
Вполне возможно, что сами исходные условия были выбраны неудачно, и это стало причиной неудачи, но в моем случае таковы были правила игры. Так же я допускаю, что проблема могла скрываться в нестабильности последней версии самого Slony, которую я использовал. В любом случае это решение не заработало, и Slony отправился на покой. Возможно в другой системной конфигурации или с другой версией Slony у Вас это получится.
Впрочем после прочтения статьи дальше Вы можете не захотеть колупаться в этой древней утилите. Да и не стоит забывать об этом: howfuckedismydatabase.com/postgres/slony.php
До второй утилиты pgpool я так и не добрался, потому что по дороге я нашел то, что и стало в конечном итоге моим решением: утилита pglogical от 2ndQuadrant.
Чтение документации по утилите и осознание кто же такие 2ndQuadrant сразу расположило меня к этому решению. Забегая вперед скажу, что судя по всему это решение может вообще войти в готовящуюся 10 версию PostgreSQL как штатное решение для логической репликации. Так что было решено играться с ним, подвинув в очереди на исследование 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
Устанавливаем необходимые библиотеки и сам пакет с игнорированием зависимостей (!), решая нашу проблему нежелания утилиты устанавливаться на что-либо кроме Postgre:
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), описание которой можно найти на миллионе ресурсов, включая документацию Postgre, и после прохождения простеньких шагов настройки самой утилиты мы можем убедиться, что репликация работает.
Буду рад услышать замечания по сути и предложения по повествованию. Самые лучшие предложения будут реализованы в виде правок к статье.