Балансировка читающих запросов PostgreSQL 15: инструменты и решения

    При использовании потоковой репликации в PostgreSQL 15 часто возникает задача разгрузить мастер-сервер от большого количества коротких запросов на чтение. Если приложение является «черным ящиком» и не поддерживает разделение запросов на запись и чтение на своей стороне, а также подключается к базе под единственным пользователем, выбор подходящего инструмента становится критическим. В этой статье мы рассмотрим основные способы балансировки нагрузки между мастером и репликой, включая Pgpool-II, HAProxy, pgBouncer и другие альтернативы.

    Почему стандартная репликация не решает проблему?

    Потоковая репликация PostgreSQL предназначена для обеспечения отказоустойчивости и горизонтального масштабирования чтения. Однако без дополнительного промежуточного слоя приложение само должно знать, на какой узел отправлять запросы. Если приложение не умеет различать SELECT и INSERT, все запросы уходят на мастер, что приводит к его перегрузке. Для автоматического распределения нагрузки используются прокси-серверы и балансировщики.

    Основные инструменты для балансировки чтения

    1. Pgpool-II

    Pgpool-II - это мощный прокси-сервер для PostgreSQL, который поддерживает балансировку нагрузки, пул соединений, репликацию и парсинг запросов. Он анализирует каждый SQL-запрос и перенаправляет SELECT на реплики, а INSERT/UPDATE/DELETE - на мастер. Однако парсинг всех запросов действительно может потреблять значительные ресурсы CPU, особенно при высокой интенсивности. Для снижения нагрузки рекомендуется настроить пул соединений и отключить ненужные функции (например, логирование каждого запроса).

    2. HAProxy с модулем проверки

    HAProxy - это высокопроизводительный TCP/HTTP балансировщик, который может работать на транспортном уровне. Для PostgreSQL его обычно настраивают с использованием опции option pgsql-check для проверки здоровья узлов. Однако HAProxy не умеет парсить SQL - он распределяет все соединения по кругу (round-robin) или по другим алгоритмам. Это означает, что запросы на запись могут попасть на реплику, что вызовет ошибку. Чтобы избежать этого, можно использовать HAProxy в связке с Pgpool-II или настроить два порта: один для записи (только мастер), другой для чтения (все узлы), но это требует изменений в приложении.

    3. pgBouncer с поддержкой маршрутизации

    pgBouncer - это легковесный пулер соединений для PostgreSQL. В версии 1.16+ появилась экспериментальная поддержка маршрутизации запросов (query routing), которая позволяет перенаправлять SELECT на реплики. Однако эта функция еще нестабильна для продакшн-нагрузок. pgBouncer потребляет меньше ресурсов, чем Pgpool-II, но его возможности по балансировке ограничены.

    4. PostgreSQL с расширением pg_rewrite

    Существуют решения на уровне базы данных, например, использование правил перезаписи запросов (rules) или триггеров, чтобы перенаправлять SELECT на реплику. Однако это сложно в реализации и может привести к проблемам с согласованностью данных. Для «черного ящика» такой подход не рекомендуется из-за высокой сложности и рисков.

    Сравнение производительности и потребления ресурсов

    Основная проблема Pgpool-II - это накладные расходы на парсинг SQL. При большом количестве коротких запросов (например, 10 000 SELECT в секунду) Pgpool-II может стать узким местом. В таких случаях лучше использовать HAProxy на транспортном уровне, но с условием, что приложение не отправляет запросы на запись на реплику. Если это невозможно, компромиссным решением является связка: HAProxy для балансировки соединений (с отправкой всех запросов на мастер), а на мастере настроить pgBouncer для кэширования и пула. Это не разгрузит мастер, но снизит накладные расходы на установку соединений.

    Рекомендации по выбору инструмента

    • Если приложение не различает запросы на запись и чтение - используйте Pgpool-II в режиме балансировки нагрузки с отключенным логированием и настройкой пула соединений. Это безопасно, но требует достаточных ресурсов CPU.
    • Если вы готовы изменить конфигурацию приложения - разделите подключения: один пул для записи (только мастер), другой для чтения (мастер + реплики). Тогда можно использовать HAProxy или pgBouncer.
    • Если важна максимальная производительность - рассмотрите использование HAProxy с двумя портами, но учтите, что это потребует доработки на стороне приложения или использования дополнительного прокси.

    Заключение

    Для балансировки читающих запросов в PostgreSQL 15 без изменений в приложении наиболее подходящим инструментом является Pgpool-II. Несмотря на опасения по поводу потребления ресурсов, современные версии Pgpool-II (4.4+) оптимизированы и могут обрабатывать десятки тысяч запросов в секунду на обычном сервере. Если нагрузка критична, рекомендуется провести нагрузочное тестирование с реальными данными. Альтернативы, такие как HAProxy, требуют либо модификации приложения, либо не гарантируют корректной маршрутизации запросов на запись.

    Часто задаваемые вопросы