В ноябре 2020 года мы начали крупную миграцию для обновления кластера PostgreSQL с версии 9.6 на 12.4. В этом посте я вкратце расскажу про нашу архитектуру в компании Coffee Meets Bagel, объясню, как даунтайм апгрейда удалось снизить ниже 30 минут, и расскажу про то, что мы узнали в процессе.
Для справки: Coffee Meets Bagel — это приложение для романтических знакомств с системой курирования. Каждый день наши пользователи получают в полдень по их часовому поясу ограниченную партию высококачественных кандидатов. Это приводит к хорошо предсказуемым закономерностям нагрузки. Если посмотреть данные за последнюю неделю от момента написания статьи, у нас в среднем получается 30 тысяч транзакций в секунду, в пике — до 65 тысяч.
До обновления у нас работали 6 серверов Postgres на инстансах i3.8xlarge в AWS. Они содержали одну главную ноду, три реплики для раздачи веб-трафика только для чтения, балансируемые с помощью HAProxy, один сервер для асинхронных воркеров и один сервер для ETL [Extract, Transform, Load] и Business Intelligence.
Для поддержания парка реплик в актуальном состоянии мы полагаемся на встроенную в Postgres потоковую репликацию.
Последние несколько лет мы заметно игнорировали наш уровень данных, и как результат, он слегка устарел. Особенно много «костылей» поднабрал в себя наш основной сервер — он находится в онлайне уже 3,5 года. Различные системные библиотеки и службы мы патчим без остановок сервера.
Мой кандидат для подреддита r/uptimeporn
Как итог, накопилось множество странностей, которые заставляют понервничать. К примеру, новые сервисы в systemd
не запускаются. Пришлось настраивать запуск агента datadog
в сессии screen
. Иногда SSH переставал отвечать при загрузке процессора выше 50 %, а сам сервер исправно отдавал запросы базы данных.
А ещё свободное место на диске начало подходить к опасным значениям. Как я упоминал выше, Postgres работал на инстансах i3.8xlarge в EC2, у которых 7,6 ТБ хранилища NVMe. В отличие от EBS, здесь размер диска динамически менять нельзя — что заложено изначально, то и будет. И мы заполнили примерно 75 % диска. Стало понятно, что для поддержания будущего роста размер инстанса придётся менять.
Нам известны три способа выполнить обновление Postgres: создание резервной копии и восстановление из неё, pg_upgrade и логическая репликация pglogical.
От первого способа, восстановления из резервной копии, мы отказались сразу: для нашего датасета на 5,7 ТБ он занял бы слишком много времени. При своей скорости приложение pg_upgrade не удовлетворяло требованиям 2 и 3: это инструмент для миграции на той же машине. Поэтому мы выбрали логическую репликацию.
Про ключевые особенности работы pglogical написано уже достаточно. Поэтому вместо повторения прописных истин я просто приведу статьи, которые оказались полезными для меня:
Мы создали новый primary-сервер Postgres 12 и с помощью pglogical синхронизировали все наши данные. Когда он синхронизировался и перешёл к репликации входящих изменений, мы начали добавлять за него потоковые реплики. После настройки новой потоковой реплики мы включали её в HAProxy, а одну из старых версии 9.6 удаляли.
Этот процесс продолжался до полного отключения серверов Postgres 9.6, кроме мастера. Конфигурация приняла следующий вид.
Затем настал черёд переключения кластера (failover), на что мы запросили окно технических работ. Процесс переключения тоже хорошо задокументирован в Интернете, поэтому я расскажу лишь про общие шаги:
CHECKPOINT
) на старом мастере.В целом, переход прошёл отлично. Несмотря на столь крупные изменения в нашей инфраструктуре, незапланированного даунтайма не случилось.
При общем успехе операции пара проблем по пути всё же встретилась. Самая страшная из них чуть не убила наш мастер Postgres 9.6…
Обозначим для начала контекст: как работает pglogical? Процесс передачи (sender) на поставщике (provider, в данном случае наш старый мастер 9.6) декодирует упреждающий журнал WAL [write-ahead log], извлекает логические изменения и посылает их на подписчика (subscriber).
Если подписчик отстаёт, то поставщик будет хранить сегменты WAL, чтобы когда подписчик его нагонит, никаких данных не потерялось.
При первом добавлении таблицы в поток репликации приложению pglogical сначала нужно синхронизировать данные таблицы. Это выполняется с помощью команды Postgres COPY
. После этого сегменты WAL начинают копиться на поставщике, чтобы изменения за время работы COPY
получилось передать на подписчика после изначальной синхронизации, гарантируя отсутствие потери данных.
На практике это означает, что при синхронизации большой таблицы на системе с большой нагрузкой по записям/изменениям нужно тщательно следить за использованием диска. При первой попытке синхронизации нашей самой крупной (4 ТБ) таблицы команда с оператором COPY
работала больше суток. За это время на ноде поставщика набралось больше одного терабайта упреждающих журналов WAL.
Как вы можете помнить по уже сказанному, на наших старых серверах баз данных оставалось всего по два терабайта свободного дискового пространства. Мы оценили по заполненности диска сервера подписчика, что скопировалась всего четверть таблицы. Поэтому процесс синхронизации пришлось немедленно остановить — диск на мастере кончился бы раньше.
Доступное дисковое пространство на старом мастере при первой попытке синхронизации
Чтобы ускорить процесс синхронизации, мы внесли следующие изменения в базу данных подписчика:
fsynch
переключили на off
;max_wal_size
на 50GB
;checkpoint_timeout
на 1h
.Эти четыре действия значительно ускорили процесс синхронизации на подписчике, и наша вторая попытка синхронизации таблицы завершилась за 8 часов.
Когда pglogical обнаруживает конфликт, приложение оставляет в логах запись вида «CONFLICT: remote UPDATE on relation PUBLIC.foo. Resolution: apply_remote
».
Однако выяснилось, что каждое обработанное подписчиком изменение строк вносилось в журнал как конфликт. За несколько часов репликации база данных подписчика оставляла после себя гигабайты файлов логов с конфликтами.
Эту проблему удалось решить заданием параметра pglogical.conflict_log_level = DEBUG
в файле postgresql.conf
.
Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…
Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…
Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…
У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…
24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…
27 июня Яндекс проведет гик-фестиваль Young Con для студентов и молодых специалистов, которые интересуются технологиями и хотят работать в IT.…