Налаштування PostgreSQL високої доступності через PgPool-II

Простій вузла бази даних зупиняє продажі й підтримку: клієнти йдуть, а команда вручну відновлює роботу. Ми налаштовуємо відмовостійкий кластер під ключ — база переживає відмову сервера без втрати даних, перемикання займає секунди, час простою скорочується в рази.
Часті запитання

PgPool-II: що ламається при відмові вузла бази даних

Основний вузол бази перестає відповідати в найневдаліший момент — наприклад, уночі, коли черговий інженер дізнається про це із системи оповіщень.

Застосунок у цей момент тримає відкриті з'єднання до вузла, що відмовив, а не до резерву: пул ще не перебудований, маршрутизація не перемкнута. Записи та замовлення починають падати з помилкою з'єднання, а необроблені запити накопичуються в черзі.

Далі починається ручна робота. Резервний вузол потрібно перевести в режим запису, перемкнути на нього трафік, переконатися, що репліка наздогнала основний за журналом, і лише потім повернути застосунок до роботи.

Поки це відбувається, частина запитів губиться безповоротно — їх ніхто не переграє, бо черга вже розійшлася по клієнтах і розпалася на рівні з'єднання.

PgPool-II ставиться між застосунком і базою саме для того, щоб цей сценарій не розгортався вручну. Він тримає власний пул з'єднань, періодичними перевірками стежить за станом вузлів і при відмові сам виключає вузол, що впав, з маршрутизації, а резервний переводить у режим запису.

Застосунок продовжує отримувати з'єднання з пулу — для сервісу змінюється адреса призначення, а не сам факт доступності бази.

Але присутність PgPool-II у схемі сама по собі не прибирає точку відмови. Якщо він запущений в одному екземплярі, без резервування самого пулу і без вивірених таймаутів перевірки, відмова просто переїжджає з бази на нього. Нижче розбираємо, як це закривається.

Що дає відмовостійкий кластер баз даних

Відмовостійкість проявляється не в спокійній роботі, а в перші секунди після збою. Тому дивимося не на заявлену підтримку реплікації, а на шкалу часу: як швидко балансувальник помічає вузол, що впав, хто перемикає трафік і що в цей момент бачить застосунок.

Застосунок підключається до однієї адреси, а PgPool-II розподіляє вхідні з'єднання між серверами. Перевірка доступності йде з коротким інтервалом: після кількох невдалих відгуків вузол виключається з видачі, решта приймають його трафік.

Помилок з'єднання на боці застосунку немає — змінюється лише внутрішня маршрутизація, а час відновлення вимірюється секундами замість ручного розбору.

Далі вмикається розділення читання і запису: запити на вибірку йдуть на репліки, змінювальні — на основний вузол. Застосунок про це не знає, рядок підключення і код залишаються попередніми.

На типовому навантаженні на репліки йде до двох третин звернень, і основний вузол перестає бути єдиною точкою і за навантаженням, і за відмовами.

Передбачуваність тут важливіша за пікову продуктивність. Деградація одного вузла перетворюється на подію з відомим сценарієм: частина запитів сповільнюється, але сервіс залишається доступним.

Клас відмов «упав сервер — лежить весь продукт» зникає з переліку ризиків, а поведінка кластера перевіряється на навчаннях, а не з'ясовується в момент реальної аварії.

Режими роботи PgPool-II та їхні обмеження

Відмовостійкий контур на PgPool-II збирають кількома способами, і балансувальник потрібен не завжди. Ключове питання — що саме потрібно: переживати відмову основного вузла, розподіляти читаюче навантаження або гасити сплески коротких підключень. Від цього залежить, де стане PostgreSQL, а де — проміжний шар.

Варіант Коли підходить Обмеження
Потокова реплікація гарячого резерву без балансувальника Один основний вузол і резерв, читання з резерву, перемикання за регламентом Автоматичного перемикання при відмові немає; адреси вузлів прописані в конфігурації застосунку
PgPool-II у режимі реплікації запитів Єдина адреса для застосунку та автоматичне перемикання при відмові Без сторожового модуля можливе розщеплення кластера при обриві зв'язку; читання з реплік відстає
PgPool-II як балансувальник з'єднань Багато коротких підключень, сплески, жорсткий ліміт з'єднань на сервері Відмовостійкості не дає — лише утримання й перерозподіл з'єднань
Логічна реплікація вибіркових таблиць Перенесення між мажорними версіями, винесення частини даних на окремий контур Немає автоматичного перемикання, затримка вища, склад об'єктів має збігатися

Що перевірити перед вибором

Режим реплікації запитів не знімає обмежень самої СУБД: запити, чутливі до актуальності даних, маршрутизуються на основний вузол, а розширення мають стояти на всіх вузлах.

Сумісність перевіряють на піковому навантаженні — затримку реплікації, поведінку при обриві каналу і коректне повернення старого основного вузла в стрій.

Як ми впроваджуємо відмовостійкий кластер: етапи робіт

Кластер високої доступності збирається не «на живу», а за послідовністю, де кожен крок підтверджується перевіркою. Нижче — порядок робіт, за яким ми ведемо проєкт: від аудиту до передачі зміні замовника. На кожному етапі видно, що вже зроблено, чим це перевірено і які ризики залишилися відкритими.

  1. Аудит поточної схеми та точок відмови. Розбираємо контур як є: де проходить запис, хто тримає з'єднання, як влаштована реплікація. Виписуємо одиничні точки — один вузол запису, балансувальник без резерву, ручне переведення при збої — і оцінюємо ціну простою кожної.
  2. Проєктування контуру. Фіксуємо ролі вузлів (ведучий, резервний, вузли читання), схему потоків даних між PgPool-II, серверами баз і застосунками, правила маршрутизації запитів на читання і запис, режим розподілу навантаження.
  3. Налаштування вузлів і перевірка перемикання. Піднімаємо пул з'єднань, реплікацію, перевірки живучості й автоматичне перемикання ролей. Окремо перевіряємо, що застосунок переживає зміну ведучого вузла без правок у коді.
  4. Випробування відмовою на стенді. По черзі виводимо з ладу кожен вузол і зв'язок між майданчиками: дивимося час перемикання, поведінку черги запитів і те, які транзакції губляться, а які ні.
  5. Прогін під навантаженням. Подаємо профіль, близький до робочого: пікові з'єднання, важкі звіти, довгі транзакції. Перевіряємо, що перемикання вкладається в узгоджене вікно і під навантаженням.
  6. Передача в експлуатацію та навчання зміни. Віддаємо конфігурації, схему ролей і потоків, регламент перемикання і розбору збоїв. Проводимо навчання зі зміною замовника, щоб переведення вузлів робилося за інструкцією, а не з пам'яті.

Конфігурації, схеми та регламенти: артефакти впровадження

Впровадження вважається закритим не коли вузли піднялися, а коли в замовника залишається комплект артефактів, за яким контур можна супроводжувати власними силами. Частина файлів іде в репозиторій конфігурацій, частина — у базу знань чергової зміни. Нижче — що саме передаємо.

  • Робочі конфігурації відмовостійкого контуру — файли PgPool-II, вузлів реплікації і менеджера кластера з параметрами під ваш профіль навантаження, а не демонстраційні. Зберігаються під контролем версій, щоб налаштування можна було відкотити, а не відновлювати з пам'яті.
  • Схема контуру — актуальна топологія: ролі вузлів, маршрути трафіку, точки відмови та порядок їх проходження. Оновлюється при кожній зміні, а не живе в голові одного інженера.
  • Правила доступу та ролі — матриця прав на вузли, режимні функції балансувальника і моніторинг; окремі облікові записи для чергового і для автоматизації, розділення читання і зміни.
  • Регламент перемикання — покроковий сценарій планового й аварійного переведення ролей, з очікуваним часом, критеріями «пора втручатися» і порядком повернення вузлів у стрій.
  • Інструкція з відновлення вузла — що робити при відставанні або випадінні репліки: перевірка синхронності, умови догону без повного перестворення, команди для типових збоїв.
  • Спостережуваність і оповіщення про збої — набір метрик (відставання реплік, стан вузлів, частка помилок маршрутизації) з порогами, за яких черговий отримує сигнал, а не дізнається про збій із скарг.
  • Записи навчань — фактичний час відновлення за підсумками тренувань і список правок, внесених до регламенту після кожного.

Кейс: простій при відмові вузла скоротився в рази

Вихідна схема та її слабкі місця

Сервіс з постійним потоком записів тримався на одному основному вузлі та гарячому резерві, а перемикання виконував черговий інженер вручну.

При відмові основного вузла застосунок отримував помилки запису, поки резерв не піднімали і не перенаправляли трафік: простій сягав десятків хвилин, а частину незавершених транзакцій розбирали і повторювали руками.

Слабке місце було не в самому резерві, а у відсутності автоматичного арбітра — рішення про перехід ухвалювала людина за непрямими ознаками і з затримкою.

Що змінили і що показали метрики

Перед кластером поставили PgPool-II: він тримає пул з'єднань, періодично опитує вузли і сам ініціює перемикання на резерв, коли основний перестає відповідати.

Частка автоматичних перемикань зросла з нуля майже до всіх відмов, які фіксує моніторинг; ручний розбір залишився лише для сценаріїв із втратою мережі між вузлами, де потрібне усвідомлене рішення.

Простій при відмові вузла скоротився в рази: перемикання вкладається в секунди, застосунок перепідключається до нового основного вузла, а не чекає інженера.

Пул з'єднань зняв навантаження на базу під піками — застосунок більше не відкриває лавину нових підключень на кожен сплеск, і черга запитів перестала впиратися в ліміт з'єднань.

Чим відрізняється балансування з'єднань від реплікації

Реплікація і балансування вирішують різні задачі, і плутати їх дорого. Реплікація відповідає за те, щоб копія даних існувала на іншому вузлі: основний вузол передає зміни потоком, резервний застосовує їх і доступний лише на читання.

Балансування відповідає за маршрут запиту — на який вузол він піде і що станеться з ним у момент відмови.

Налаштувавши потокову реплікацію, навантаження читання ви не розподілите. Репліка отримує ті самі дані, але застосунок звертається до основного вузла, поки між ним і базами немає маршрутизатора.

PgPool-II працює тут: розбирає запит, зміни надсилає на основний вузол, читання розкладає по репліках і тримає пул з'єднань.

Схему вибирають за профілем навантаження. Якщо переважають записи, репліки основний вузол не розвантажать — вони лише повторюють зміни.

Якщо домінує читання, розподіл запитів читання знімає з основного вузла помітну частку звернень, але застосунок має миритися з відставанням репліки.

Звідси головний ризик: поки вузли розходяться, репліка віддає застарілі дані — користувач не бачить щойно збереженого запису. Зворотна помилка гірша: зміна йде на вузол, який маршрутизатор помилково вважає основним.

Тоді розходяться вже самі вузли, і це не лікується перезапуском. Тому поруч із балансуванням ідуть перевірки стану вузлів, автоматичне перемикання на резервний і захист від розщеплення кластера.

Що робити при відставанні — чекати, виключати репліку з розподілу або переводити читання на основний вузол — вирішують заздалегідь.

Технічні сумніви перед впровадженням: розбір

Перед впровадженням PgPool-II у команди спливають одні й ті самі сумніви: чи доведеться правити застосунок, чи потрібен простій, чи спрацює автоматичне перемикання, що робити при розходженні даних.

Застосунок доведеться переписувати?

Ні. PgPool-II стає між застосунком і кластером і говорить тією ж протоколою, що й звичайний сервер баз даних. Змінюється лише рядок підключення — драйвери та бібліотеки доступу до даних продовжують працювати. Точково перевіряємо запити, зав'язані на одному вузлі: послідовності та серверні курсори.

Впровадження на працюючому кластері — це простій?

Простій не потрібен. PgPool-II піднімається поруч із поточним кластером; спочатку переводимо на нього читання і дивимося поведінку під навантаженням, запис — останнім. На це потрібна пауза в секунди, щоб закрилися відкриті транзакції. Відкат — повернення застосунків на попередній рядок підключення.

Як перевірити автоматичне перемикання?

На стенді, наближеному до бойового: зупиняємо основний вузол і фіксуємо час до переведення репліки в основний, число втрачених транзакцій, поведінку застосунку при розриві з'єднання. Потім повторюємо на репетиції бойового контуру — зі звітом і логами.

Що буде при розходженні даних?

PgPool-II стежить за відставанням реплік: при перевищенні порогу вузол виключається з видачі читання — застосунок не отримує застарілі дані. Вузол, що випав після збою, перезбирається з копії основного.

Затримка реплікації, доступність і зміна ролі виводяться на панель моніторингу: алерт приходить раніше, ніж проблему помітять користувачі.

Обговоримо задачу і повернемося з планом робіт

Щоб оцінка спиралася на факти, а не на припущення, для старту достатньо опису поточної схеми і характеру навантаження. Ми розберемо, де зараз точка відмови, як розподіляються читання і запис між вузлами і чи готова єдина точка входу для застосунків.

Від замовника потрібно небагато:

  • Схема контуру: число вузлів PostgreSQL, наявність реплік, режим реплікації, хто зараз керує зміною ролі основного вузла.
  • Профіль навантаження: частка читання і запису, пікові періоди, вимоги до часу відповіді на запит.
  • Поведінка застосунків: як переживають розрив з'єднання, чи використовують єдину адресу підключення, чи готові коректно повторити запит після перемикання.
  • Парк з'єднань: скільки клієнтів підключається одночасно і чи є пул на боці застосунку.
  • Вимоги до відмови: допустимий час недоступності на запис і на читання, чи потрібне автоматичне повернення ролі на попередній вузол.
  • Регламенти: вікно обслуговування, доступи до серверів і до систем моніторингу.

За підсумками обговорення надсилаємо план впровадження: склад і порядок робіт, етапність (підготовка вузлів, увімкнення розподілу читання, перевірка перемикання ролі, навантажувальна перевірка), критерії приймання і порядок передачі із супроводом. Опишіть задачу — повернемося з оцінкою та планом.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139