Масштабирование PostgreSQL: готовые решения от Skype
Автор: Иван Золотухин
Совсем недавно компания Skype выложила в открытое пользование под лицензией BSD ряд своих наработок, анонсированных прошлым летом на конференции, посвященной 10-летию PostgreSQL. Эти решения позволяют полностью решить проблемы масштабирования и резервирования OLTP систем, а также организовать необходимую синхронизацию с OLAP базами данных, решив таким образом 2 самых основных проблемы, с которыми сталкиваются разработчики баз данных при построении высоконагруженных систем. В пресс-релизы об этом событии вошли лишь краткие описания продуктов от Skype, поэтому возникла необходимость описать более подробно те возможности, которые появились у разработчиков и администраторов баз данных PostgreSQL.
PL/Proxy
PL/Proxy представляет собой прокси-язык для удаленного вызова процедур и партицирования данных между разными базами. Основная идея его использования заключается в том, что появляется возможность вызывать функции, расположенные в удаленных базах, а также свободно работать с кластером баз данных (например, вызвать функцию на всех узлах кластера, или на случайном узле, или на каком-то одном определенном).
Чем PL/Proxy может быть полезен? Он существенно упрощает горизонтальное масштабирование системы. Становится удобным разделять таблицу с пользователями, например, по первой латинской букве имени -- на 26 узлов. При этом приложение, которое работает непосредственно с прокси-базой, ничего не будет замечать: запрос на авторизацию, например, сам будет направлен прокси-сервером на нужный узел. То есть администратор баз данных может проводить масштабирование системы практически независимо от разработчиков приложения.
PL/Proxy позволяет полностью решить проблемы масштабирования OLTP систем. В систему легко вводится резервирование с failover-ом не только по узлам, но и по самим прокси-серверам, каждый из которых работает со всеми узлами.
Несколько примеров от Skype
1. Простейший пример удаленного вызова функции. Соединяемся с dbname=users выполняем запрос SELECT * FROM get_user_email($1); на удаленной базе:
CREATE FUNCTION get_user_email(username text) RETURNS text AS $$ CONNECT 'dbname=users'; $$ LANGUAGE plproxy;
2. Пример с партицированием. Пользователи разделены по разным базам, номер партиции вычисляется функцией hashtext(username):
CREATE FUNCTION get_user_email(username text) RETURNS text AS $$ CLUSTER 'userdb'; RUN ON hashtext(username); $$ LANGUAGE plproxy;
3. Функции на прокси-сервере создаются с такой же сигнатурой, что и на удаленном сервере. В теле прокси-функции нужно определять лишь путь до удаленного сервера:
CREATE FUNCTION pwd_check(text, text) RETURNS boolean $$ SELECT 1 FROM users WHERE name=$1 AND PWD=$2; IF FOUND THEN RETURN true; ELSE RETURN false; $$ LANGUAGE plpgsql; CREATE FUNCTION pwd_check(text, text) RETURNS boolean $$ CLUSTER userdb_cluster; PARTITION BY hashtext($1); $$ LANGUAGE plproxy;
4. Есть возможность выполнять произвольные SQL запросы:
CREATE FUNCTION get_user_location(text) RETURNS text AS $$ CLUSTER 'userdb'; RUN ON hashtext($1); SELECT email FROM users WHERE user = $1; $$ LANGUAGE plproxy;
Недостатки и ограничения
- все запросы и вызовы функций вызываются в autocommit-режиме на удаленных серверах
- в теле функции разрешен только один SELECT; при необходимости нужно писать отдельную процедуру
- при каждом вызове прокси-сервер стартует новое соединение к бакенд-серверу; в высоконагруженных системах целесообразно использовать менеджер для кеширования соединений к бакенд-серверам, для этой цели идеально подходит PgBouncer
- изменение конфигурации кластера (количества партиций, например) требует перезапуска прокси-сервера
PgBouncer
PgBouncer представляет собой простой и быстрый менеджер соединений для PostgreSQL. Он поддерживает три режима управления соединениями:
- Session Pooling. Наиболее "вежливый" режим. При начале сессии клиенту выделяется соединение с сервером; оно приписано ему в течение всей сессии и возвращается в пул только после отсоединения клиента.
- Transaction Pooling. Клиент владеет соединением с бакендом только в течение транзакции. Когда PgBouncer замечает, что транзакция завершилась, он возвращает соединение назад в пул.
- Statement Pooling. Наиболее агрессивный режим. Соединение с бакендом возвращается назад в пул сразу после завершения запроса. Транзакции с несколькими запросами в этом режиме не разрешены, так как они гарантировано будут отменены.
К достоинствам PgBouncer относится очень низкое потребление памяти (менее 2КБ на соединение по умолчанию), отсутствие привязки к одному серверу баз данных (может работать с разными хостами), возможность изменения большинства настроек без рестарта, а также возможность онлайн-перезапуска: PgBouncer сам перенесет открытые сокеты в новый процесс. Из недостатков стоит отметить разве что отсутствие поддержки протоколов старее V3, что требует использования в качестве бакенда сервера PostgreSQL версии новее, чем 7.4, но в настоящее время это уже не является серьезным ограничением. Для низкоуровневой работы с сокетами PgBouncer использует libevent.
WalMgr
Скрипт, написанный на python, максимально облегчающий процедуру разворачивания сервера с горячим бекапом на основе трансфера логов, а в случае отказа мастер-сервера -- быстрого переключения нагрузки на резервный сервер. Все весьма просто:
[ .. настраиваем небольшие конфиг файлы .. ]
master$ walmgr setup
master$ walmgr backup
slave$ walmgr restore
[ .. мастер-сервер отказал, переключаем нагрузку на резервный сервер с бекапом: ]
slave$ walmgr restore
Londiste
Представляет собой движок для организации репликации, написанный на языке python. Основные принципы: надежность и простота использования; из-за этого данное решение имеет меньше функциональности, чем Slony-I. Londiste использует в качестве транспортного механизма очередь PgQ (описание этого более чем интересного проекта остается за рамками данного мини-обзора, поскольку он представляет интерес скорее для низкоуровневых программистов баз данных, чем для конечных пользователей -- администраторов СУБД PostgreSQL). Отличительными особенностями решения являются:
- возможность потабличной репликации
- начальное копирование ничего не блокирует
- возможность двухстороннего сравнения таблиц
- простота установки
К недостаткам можно отнести:
- отсутствие поддержки sequence делает невозможным поддержание failover-сервера актуальным (для этой цели нужно использовать WalMgr)
- отсутствие поддержки каскадной репликации
Пример использования Londiste с инсталляцией:
$ londiste.py replic.ini provider install $ londiste.py replic.ini subscriber install $ londiste.py replic.ini replay -d $ londiste.py replic.ini provider add users orders $ londiste.py replic.ini subscriber add users
Ссылки
- "Skype делится своими проектами", Новости PostgreSQL, Postgresmen
- "PostgreSQL at Skype", доклад Skype на PostgreSQL Anniversary Summit 2006
- Public Database Projects, Skype Developer Zone
- PlProxy, Skype Developer Zone
- SkyTools, Skype Developer Zone
- PgBouncer, Skype Developer Zone
- PlProxy, PgFoundry
- SkyTools, PgFoundry
- PgBouncer, PgFoundry
Any feedback is welcome at iz at sai dot msu dot ru
Apr 2007