Путь к масштабированию PostgreSQL: от теории к практике

от автора

«Postgres масштабируется» — нет других двух слов, которые вызывали бы больше споров. По крайней мере, в кругах, где я общаюсь, в подвале компании, где инфраструктурные эльфы заставляют Rails-приложение работать. Многие верят, вопреки всему и маркетинговым кампаниям Big NoSQL, что знакомая технология лучше, чем новый неизвестный инструмент, о котором только что рассказали на совещании руководства.

Честно говоря, я понимаю их позицию. Заставить Postgres писать больше данных может быть сложно. Вам нужно больше оборудования. В большинстве случаев его можно получить, просто нажав кнопку «Обновить». Но когда вы дошли до экземпляра r5.24xlarge с 5 репликами такого же размера, и ваши процессы vacuum всё ещё отстают от графика, ситуация становится довольно пугающей.

Именно здесь начинается испытание для настоящего инженера. На пределе возможностей. Я говорю не о WebAssembly. Я говорю об инженерном духе, который смотрит на проблему под давлением руководства и вместо того, чтобы бежать к ближайшей команде продаж с большими обещаниями (но малым количеством фактов о вашем конкретном случае), решает её, используя базовые принципы.

А базовый принцип говорит нам, что нам нужно. У Postgres закончилась пропускная способность для записи. Либо из-за блокировок при работе с WAL, либо что-то застопорило vacuum. Вероятно, это та неактивная транзакция, которая открыта уже 45 секунд, пока приложение делает запрос к Stripe, но это не наша забота. Мы — инфраструктурная команда, и наша задача — заставить базу данных работать.

Поэтому мы решили, как сообщество энтузиастов с изолентой в руках, дать Postgres то, что он хочет: больше машин. Мы собираемся разделить нагрузку по записи равномерно между 3 (нет, давайте возьмем 6, чтобы наверняка) базами данных. Если теория «чем больше, тем лучше» верна, то мы должны получить в 6 раз больше операций записи.

Выбранный путь

Забавно писать об этом. В интернете есть как минимум один (или, может быть, два) содержательных блог-поста о том, как это делается. Забавно, потому что они описывают огромную работу, проделанную командой примерно из 5 человек. Команда проверила каждый вызов ActiveRecord и psycopg2 execute, чтобы убедиться, что он содержит ключ шардирования.

Мы взяли отказывающую базу данных, обслуживающую около 100 000 пользователей в секунду, запустили десятки страшных (и в основном недокументированных) команд, чтобы сохранить слот репликации, пока мы делаем снимок, восстанавливаем его 6 разными способами и урезаем большую часть данных, чтобы синхронизировать с новой схемой шардирования.

Мы синхронизировали её с помощью логической репликации, что заняло пару дней. Эти базы данных бесценны, и одна случайная запись может нарушить целостность данных. Поэтому команда добавила триггеры, проверяющие строки, которые попадают в каждую таблицу. Мы выбрали хеш-функцию, которая есть в Postgres с версии 10 и которую нашли в глубинах списков рассылки. Это функция, которую мы можем вызвать для ручной проверки строк или перераспределения данных.

Данные разделены, но мы не сказали приложению, как их найти. Они были в 1 базе данных, теперь в 6. К счастью, Postgres имеет открытый исходный код. Мы нашли код для этой хеш-функции, переписали его на Ruby и встроили в класс ApplicationRecord. Каждый раз, когда кто-то выполняет запрос, этот код хеширует ключ шардирования и отправляет запрос на один из экземпляров, настроенных в database.yml. Если это SELECT, он получит особую обработку и будет балансироваться между 5 репликами.

Python получил более сложное решение и использует специальный координатор, созданный с использованием секционированных внешних таблиц. Он также будет обслуживать 1% межшардовых запросов, которые мы не успели распутать вовремя. Postgres иногда пугает своей универсальностью.

Команда создала 5 реплик для каждого шарда. Мы не шутили. Мы никогда больше не хотим повторять этот ручной процесс. Это должно поддерживать их работу ещё… годы. Мы не знаем, сколько именно, потому что никогда раньше не видели такого роста, но мы всегда можем добавить больше реплик. Добавление новых шардов — это проблема на будущее. Мы знаем, что можем, потому что зашли так далеко, и наш инженерный дух силён, но сейчас мы просто хотим закончить задачу.

Если вы считаете вместе со мной, у нас 36 баз данных. Достаточно места для роста ещё в 6 раз.

Пришло время написать конфигурацию Pgbouncer. Жаль, что он не может балансировать трафик за нас, но это нормально. У нас есть плагин ActiveRecord, который разберётся, а приложения на Python могут просто использовать replica-5-prod. Сейчас 22:45, за 2 часа до окна обслуживания, которое мы согласовали с бизнес-командой, которая до сих пор не понимает, почему нам нужно отключать всё приложение на несколько часов каждые две недели.

План перехода прост. Отключить базу данных и перевести приложение на новые. Достаточно просто.

Время пришло. Знакомый концерт оповещений из Datadog, Rollbar и CloudWatch начинает играть. PagerDuty звонит. Но никого не будят, мы все уже здесь. Мы забыли установить окно обслуживания, но сейчас нет времени. Бизнес отключен, и у нас есть около 5 минут, чтобы переключить конфигурации, вручную проверить, что всё работает, и снова включить трафик.

Кто-то написал скрипт на Bash для одновременной перезагрузки всех bouncers. Молодец, это хорошая идея. Инфраструктурные инженеры используют Bash для всего. Базовые принципы.

Приложение готово, мы выполнили несколько запросов и проверок, чтобы убедиться, что всё в порядке. Мы почти готовы включить систему обратно, когда один из инженеров тихо спрашивает (всё-таки сейчас 2 часа ночи):

Эй, ребята, а мы обновили последовательности?

Чёрт. Логическая репликация не обрабатывает эту мелочь, но это нормально, у нас всё ещё есть скрипт PL/pgSQL с прошлого раза. Быстрое копирование/вставка в сеанс psql с правами суперпользователя, и мы снова в деле, с достаточным пространством для роста компании и адской историей для рассказа.

Аргумент в пользу Postgres

Ладно, это, возможно, не самая жизнерадостная презентация. Для скептика всё это действительно может склонить чашу весов в любую сторону, и, возможно, DynamoDB будет лучшим выбором для их следующего нового проекта. Но если вы всё ещё читаете это, то только что увидели дорожную карту того, как можно шардировать Postgres. Это не только возможно, это вполне выполнимо, и это уже делалось.

Что нам действительно нужно сейчас — это код, который сделает это за нас. Предпочтительно автоматически, в фоновом режиме, пока мы заняты написанием новых запросов ActiveRecord для продажи товаров. Из этой веры, и потому что масштабирование Postgres должно выполняться после обеда нажатием кнопки, мы написали PgDog.

Для вас и потому что мы можем. Это, как мы полагаем, ответ на вопрос «Масштабируется ли Postgres?». Да, масштабируется. Он масштабировался и будет масштабироваться, пока мы, инженеры, делаем это возможным. PgDog — это проект с открытым исходным кодом для шардирования Postgres.

P.S. Подписывайтесь на канал

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Какой подход к масштабированию баз данных вы предпочитаете в высоконагруженных проектах?

0% Вертикальное масштабирование PostgreSQL (более мощные серверы)0
0% Шардирование PostgreSQL (как описано в статье)0
0% Переход на распределенные NoSQL решения (MongoDB, Cassandra и др.)0
0% Использование специализированных решений (Citus, Yugabyte, CockroachDB)0
100% Комбинированный подход (разные БД для разных задач)1
0% Никакой, нет необходимости0

Проголосовал 1 пользователь. Воздержавшихся нет.

ссылка на оригинал статьи https://habr.com/ru/articles/891122/


Комментарии

Добавить комментарий

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