Як визначити майстра в mysql master-slave


17

Я налаштовую реплікацію MySQL Master-slave і намагаюся розібратися, як впоратися із ситуацією з відмовою, коли я сприяю веденню до ведучого (у випадку, якщо майстер зійде).

Мій сервер додатків повинен направляти всі записи на поточний головний майстер, але я не можу використовувати серверний рівень HA між головним і веденим (серцебиття, збереження), оскільки два db-сервери знаходяться на абсолютно різних підмережах у різних фізичних місцях.

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

Чи є запит у MySQL, щоб перевірити, чи поточний сервер є майстром у репліці master-slave?


Яку версію MySQL ви використовуєте ???
RolandoMySQLDBA

Це вихід mysqlServer version: 5.5.23 MySQL Community Server (GPL)
Етан Хейон

Відповіді:


13

@RolandoMySQLDBA точно відповів на питання ... але він також зазначив, що його рішення було "швидко і брудно".

І це дуже правдиве твердження. :)

Що мене тут стосується - це не відповідь, а скоріше те, що в початковому питанні з'являється неправильне припущення:

Я можу запитати два сервери і запитати, який з них є майстром, а потім виконувати всі запити до цього.

Проблема полягає в тому, що в реплікації MySQL, майстер ніколи не знає, що він є головним.

Поняття "просування до майстра" насправді не є поняттям в асинхронній реплікації MySQL. "Просування" сервера MySQL до головної ролі - це те, що відбувається "зовні", ніж "MySQL-сервери", на відміну від того, що відбувається "внутрішнього" для MySQL-серверів.

"Просування до майстра" не робиться будь-яким видом серверного забезпечення, оскільки, технічно кажучи, кожен сервер MySQL, у якому ввімкнено бінарний журнал, є майстром, навіть якщо він ніколи не є веденим. SHOW MASTER STATUSпрацює точно так само і повертає абсолютно той самий результат, раби чи ні, а господар з 2 рабами - не більш-менш господар, ніж господар з 1 рабом або 0 рабами. Аналогічно, господар, у рабів якого все немає в автономному режимі, все ще є таким же майстром, тому що, коли раби повернуться в Інтернет, вони підберуть реплікацію там, де вони зупинилися.

У певному сенсі єдине «усвідомлення» з боку будь-якого сервера - це не те, чи він є господарем, а скоріше, чи є він рабом (або «ні»).

Ось що запитує рішення Роландо: "ти раб?" Якщо відповідь "ні", то припущення полягає в тому, що це повинен бути майстер ... що він також зазначив як хибне припущення, якщо STOP SLAVE;воно видане. Але зупинений раб все ще є рабом, тому "не раб" (у будь-який момент часу) не прирівнюється до "бути господарем".

Аналогічний тест можна зробити і передбачуваним майстром:

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

або

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

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

Що ще гірше (для будь-якого з цих сценаріїв) "таблиця" information_schema.processlist - це віртуальна таблиця, яка матеріалізується щоразу, коли її вибирають, і це вимагає часу та витрат ресурсів. Чим зайнятіший ваш сервер, тим дорожче він коштує, тому що в діяльність кожної нитки потрібно зазирнути.

Більш легким рішенням буде:

SELECT @@global.read_only;

На підлеглому ви можете / повинні встановити глобальну змінну, read_onlyщоб користувачі без SUPERпривілею не могли ненавмисно писати на неї (а у вашій програмі не повинно бути SUPER). Якщо ви вручну "просунете" раба до головної ролі, вам SET GLOBAL read_only = OFFпотрібно включити запис. (Реплікацію завжди можна записати на раба, незалежно від того, як це встановлено).

Але це все одно, я думаю, пропускає важливий момент:

Я б запропонував, щоб програма не приймала це рішення евристично в режимі master / slave, і, звичайно, не на основі з'єднання за з'єднанням. Додаток повинен використовувати або жорсткий варіант конфігурації, або додаток повинен залишатися невідомим, а призначення з'єднання бази даних обробляти чимось іншим.

Або, як мінімум, програма ніколи не повинна перемикатися, поки майстер не виходить з ладу, і тоді він ніколи не повинен перемикатися самостійно.

Ось чому я кажу, що: як тільки хтось чи що завгодно прийме «рішення» зробити іншим сервером майстром, додаток не може бути дозволено з будь-якої причини повернутися до початкового майстра, навіть після того, як він повернеться в Інтернет , без втручання.

Скажімо, ви потрапили в помилку, і сталася аварія з програмним забезпеченням; mysqld_safeналежним чином перезавантажується mysqld, і відновлення аварій InnoDB виконує бездоганно. Але це займає кілька хвилин.

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

Тепер оригінальний майстер повертається в Інтернет.

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

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

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

Тож у програмі не дуже важливо щось відкрити, оскільки вам доведеться вручну STOP SLAVEзробити тест корисним.

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

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

Ви не можете розгорнути інструменти HA на серверах MySQL через їх розділення, але ви могли реалізувати його за допомогою HAProxy, що працює на серверах додатків. Додаток підключається до "MySQL" на localhost, який зовсім не MySQL, але насправді є HAProxy ... і передає TCP-з'єднання на відповідну машину MySQL.

HAProxy може перевірити підключення до серверів MySQL і пропонувати трафік лише машині MySQL, яка приймає з'єднання і дозволяє аутентифікацію.

Поєднання HAProxy, що працює на сервері прикладних програм (його попит на ресурси не буде суттєвим порівняно з усім іншим, який повинен робити сервер додатків - це просто просто зав'язування сокетів разом і ігнорування їх корисного навантаження) ... і кругова реплікація MySQL Це був би підхід, який я, мабуть, застосував би в цьому випадку, виходячи з того, що відомо з питання.

Або для суворої налаштування вручну виконайте щось набагато простіше, ніж "відкриття", як запис у /etc/hostsфайлі сервера додатків з ім'ям хоста, яке програма використовує для підключення до MySQL, яке ви можете вручну оновити - якщо припустити, що рекламується підлеглий до майстер призначений для ручного процесу.

Або щось складніше, використовуючи кластер Percona XtraDB. Для цього, хоча б, ви хочете додати третій сервер, оскільки з 3-ма вузлами в PXC, якщо два сервери можуть бачити один одного, але ізолюватися від 1-го сервера (якщо всі три тривають і досі), два сервери продовжують працювати успішно, але 1 сервер згортається на маленьку кульку і відмовляється робити що-небудь, оскільки зрозуміє, що це повинен бути непарний. Це працює, тому що два розуміють, що вони все ще складають більшість вузлів, які були в Інтернеті до розколу мережі, а 1 розуміє, що це не так. З PXC це не має значення, до якого сервера підключається ваше додаток.

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


Перш за все, дякую за добре написану відповідь. Я думаю, ви запропонували хороше рішення. Я раніше думав про використання кругової реплікації, але читав погані речі щодо її надійності. Однак велику частину цих проблем можна запобігти, змінивши auto_increment_increment, auto_increment_offset тощо. Використання локальної програми HAProxy на серверах прикладних програм (як тільки відмовка) буде для нас добре працювати, оскільки нам не доведеться змінювати наш додаток, тому обмежуючи відмову логіка від шару програми. Я перегляну налаштування HAProxy, дякую!
Етан Хейон

1
Радий допомогти. Якщо ви ще цього ще не зробили, голосування було б вдячне. Кругова реплікація настільки ж надійна, як і ведучий / підлеглий (це та сама технологія, просто йдуть в обох напрямках), поки ви зрозумієте, як вона працює, і використовуєте її розумним чином. Поки сервери належним чином синхронізовані і програма записує лише один сервер, я ніколи не мав проблем із цим. Ці auto_increment_*змінні все ще добре використовувати в цьому випадку, « на всякий випадок» . Крім того, не забудьте використовувати binlog_format= rowабо mixed- ні statement(навіть якщо ви не робите кругової).
Michael - sqlbot

Я змінив прийняту відповідь суто тому, що це детальне пояснення допомогло мені переробити систему, щоб бути більш надійною. @ Відповідь RolandoMySQLDBA все ще правильна і вирішує проблему, яку я спочатку описав. Спасибі!
Етан Хейон

10

Якщо ви використовуєте лише Master / Slave, ось щось швидке і брудне:

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

Що це вам говорить?

  • Якщо SlaveThreadCount= 0, у вас є Майстер
  • Якщо SlaveThreadCount> 0, у вас є Раб

CAVEAT : Це працює до тих пір, поки ви не запуститеSTOP SLAVE;

Ще одна річ, яку слід спробувати, це: Якщо ви вимкнете бінарний журнал на підлеглому, і ви запускаєте SHOW MASTER STATUS;, Master надає вам поточний бінарний журнал. Раб нічого не дає тобі.


Дивовижно, це саме те, що мені потрібно. Як ви вважаєте, це безладне рішення проблеми? Єдине питання, яке я можу передбачити, - це те, як обидва сервери просуваються до майстра, але це насправді ніколи не повинно відбуватися.
Етан Хейон

Якщо ця відповідь потрібна вам, будь-ласка, позначте прийняту відповідь, натиснувши галочку на мою відповідь.
RolandoMySQLDBA

Я не можу відзначити це прийнятим протягом ще 5 хвилин :)
Етан Хейон

Без проблем. Я був радий, що можу допомогти !!!
RolandoMySQLDBA

0

виконати це твердження з підказок
mysql mysql> показати статус рабовласників;

На підлеглому він показує безліч параметрів та їх значення / статус, а на master - це Порожній набір

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.