В Ситимобил използваме база данни MySQL като основно хранилище за постоянни данни. Имаме няколко кластера с бази данни за различни услуги и цели.
Постоянната наличност на основния сървър е критичен показател за работоспособността на цялата система и нейните отделни части. Автоматичното възстановяване на кластера в случай на отказ на основния сървър значително намалява времето за реакция на инциденти и времето на престой на системата. В тази статия ще разгледам схемата за осигуряване на висока наличност (HA) на MySQL кластера на база и виртуални IP адреси (VIP).

HA решение на база VIP
Първо накратко ще обясня какво представлява нашата система за съхранение на данни.
Използваме класическа схема на репликация с един основен сървър, който е достъпен за запис, и множество реплики, които се използват само за четене. Кластерът може да съдържа междинен основен сървър – узел, който едновременно е реплика и основен за другите. Клиентите се свързват с репликите чрез HAProxy, което позволява равномерно разпределение на натоварването и лесно скалиране. Използването на HAProxy е свързано с исторически причини и в момента преминаваме на ProxySQL.
Репликацията се извършва в полусинхронен режим на база GTID. Това означава, че поне една реплика трябва да запише транзакцията в дневника, преди тя да бъде призната за успешна. Такава схема на репликация осигурява оптимален баланс между производителността и запазването на данни в случай на отказ на основния узел. По принцип всички промени се предават от основния към репликите с помощта на Row Based Replication (RBR), но част от узлите може да разполагат с mixed binlog format.
Оркестраторът периодично актуализира състоянието на топологията на кластера, анализира получената информация и в случай на проблеми може да стартира процедура за автоматично възстановяване. За самата процедура отговаря разработчикът, тъй като тя може да бъде реализирана по различни начини: на база VIP, DNS, използвайки служби за откритие на услуги (service discovery) или ръчно изработени механизми.
Един от простите начин за възстановяване на основния сървър в случай на отказ е използването на плаващи VIP адреси.
Какво трябва да знаете за това решение, преди да продължите:
- VIP — това е IP адрес, който не е свързан с конкретен физически мрежов интерфейс. Когато възелът се повреди или по време на планирани работи, можем да прехвърлим VIP на друг ресурс с минимално време на престой.
- Освобождаването и издаването на виртуален IP адрес са евтини и бързи операции.
- За работа с VIP е необходим достъп до сървъра по SSH или използване на специализирани утилити, например,
keepalived.
Нека разгледаме възможните проблеми с нашия майстор и да представим как трябва да функционира механизмът за автоматично възстановяване.
Изчезнала е мрежовата свързаност с майстора, или е възникнала проблема на ниво „желязо“, и сървърът е недостъпен.
- Оркестраторът актуализира топологията на клъстера, всяка реплика съобщава за недостъпността на майстора. Оркестраторът стартира процеса на избор на реплика, подходяща за нов майстор, и започва възстановяването.
- Опитваме се да премахнем VIP от стария майстор — безуспешно.
- Репликата преминава в ролята на майстор. Топологията се преконфигурира.
- Добавяме нов мрежов интерфейс с VIP. Тъй като не успяваме да премахнем VIP, на фоново ниво стартираме периодично изпращане на запитване gratuitous ARP. Този вид запитване/отговор позволява да се обнови таблицата за съответствие на IP и MAC адреси на свързаните комутатори, уведомявайки таким образом за местенето на нашия VIP. Това минимизира вероятността за
split brainпри възстановяването на стария майстор. - Всички нови връзки незабавно се пренасочват към новия майстор. Старите връзки завършват неуспешно, извършват се повторни повиквания към БД на ниво приложение.
Сървърът работи в нормален режим, възникна отказ на ниво СУБД.
Алгоритъмът е аналогичен на предходния случай: актуализиране на топологията и стартиране на процеса на възстановяване. Тъй като сървърът е наличен, успешно освобождаваме VIP от стария майстор, преместваме го на новия и изпращаме няколко ARP запитвания. Възможното възстановяване на стария майстор не трябва да влияе на преконфигурирания клъстер и функционирането на приложението.
Други проблеми
Отказ на реплики или междинни майстори не води до автоматични действия и изисква ръчно намесване.
Виртуалният мрежов интерфейс винаги се добавя временно, тоест след рестартиране на сървъра VIP не се назначава автоматично. Всеки екземпляр на БД по подразбиране се стартира в режим само за четене, оркестраторът автоматично превключва новия майстор на запис и се опитва да установи само за четене на стария майстор. Тези действия са насочени към намаляване на вероятността split brain.
По време на възстановяване могат да възникнат проблеми, за които също е важно да се уведомява през UI на оркестратора, освен стандартните средства за мониторинг. Разширихме REST API, добавяйки тази възможност ( в момента е на разглеждане).
Общата схема на HA-решението е представена по-долу.

Избор на нов майстор
Оркестраторът е достатъчно умен и се старае да избере като нов майстор по следните критерии:
- отставането на репликата от майстора;
- версията на MySQL на майстора и репликата;
- тип репликация (RBR, SBR или смесена);
- разположение в един или различни дата-центрове;
- наличие
неправилен GTID— транзакции, които са били извършени на репликата и не присъстват на майстора; - също така се вземат предвид потребителските правила за избор.
Не всяка реплика е идеален кандидат за ролята на майстор. Например, репликата може да се използва за архивиране на данни, или сървърът има по-слаба конфигурация на „хардуера“. Оркестраторът има ръчни правила, с които можете да настроите собствените си предпочитания за избор на кандидат от най-предпочитаните до игнорираните.
Време за реакция и възстановяване
В случай на инцидент е важно да се минимизира времето за престой на системата, затова ще разгледаме параметрите на MySQL, които влияят на изграждането и обновлението на топологията на кластера от оркестратор:
- — брой секунди, през които репликата очаква получаване на нови данни или heartbeat-сигнал от майстора, преди връзката да бъде призната за загубена и да се извърши повторно свързване. Колкото по-малка е стойността, толкова по-бързо репликата може да определи, че връзката с майстора е нарушена. Настройваме тази стойност на 5 секунди.
- — брой секунди между опитите за повторно свързване. При мрежови проблеми ниската стойност на този параметър ще позволи бързо повторно свързване и ще предотврати активирането на процеса за възстановяване на клъстера. Препоръчваната стойност е 1 секунда.
MASTER_RETRY_COUNT— максимален брой опити за повторно свързване.MASTER_HEARTBEAT_PERIOD— интервал в секунди, след който майсторът изпраща сигнал за състояние (heartbeat). По подразбиране е равен на половината от стойносттаslave_net_timeout.
Настройки на оркестратора:
DelayMasterPromotionIfSQLThreadNotUpToDate— ако е равен наtrue, ролята на майстора няма да бъде приложена на кандидата за реплика, докато SQL потока на репликата не изпълни всички неприложени транзакции от Relay Log. Използваме тази опция, за да не загубим транзакции в условия на забавяне на всички кандидати за реплика.InstancePollSeconds— честота на изграждане и обновяване на топологията.RecoveryPollSeconds— честота на анализ на топологията. При откриване на проблем стартира възстановяване на топологията. Това е, равна на 1 секунда.
Всеки възел на клъстера се опитва да се свърже с оркестратора веднъж на InstancePollSeconds секунди. При откриване на проблем, състоянието на клъстера се принуждава, след което се взема окончателно решение за изпълнение на възстановяването. Чрез експериментиране с различни параметри на БД и оркестратора, успяхме да намалим времето за реакция и възстановяване до 30 секунди.
Тестов стенд
Тестването на схема за висока наличност (HA) започнахме с разработката на локален и последващо внедряване в тестова и производствена среда. Локалният стенд е напълно автоматизиран на базата на Docker и позволява експериментиране с конфигурацията на оркестратора и мрежата, мащабиране на клъстера от 2-3 сървъра до няколко десетки и провеждане на учения в безопасна среда.
По време на ученията избираме един от методите за емулиране на проблем: моментално спиране на майстора с помощта на kill -9, меко приключване на процеса и спиране на сървъра (docker-compose stop), емилиране на проблеми с мрежата с помощта на iptables -j REJECT или iptables -j DROP. Очакваме следните резултати:
- оркестраторът да открие проблеми с майстора и да обнови топологията не по-дълго от 10 секунди;
- автоматично да се стартира процедурата за възстановяване: мрежовата конфигурация да се промени, ролята на майстора да премине на реплика, топологията да се преустрои;
- новият майстор ще бъде наличен за запис, живите реплики няма да бъдат загубени по време на преустройството;
- данните ще започнат да се записват в новия майстор и да се репликират;
- общото време за възстановяване няма да надвишава 30 секунди.
Както знаете, системата може да се държи по различен начин в тестова и производствена среда поради различна конфигурация на „желязото“ и мрежата, както и различия в синтетичното и реално натоварване и т.н. Ето защо периодично провеждаме учения в реални условия, проверявайки как системата се държи при загуба на мрежова свързаност или деградация на отделни части. В бъдеще искаме да изградим напълно идентична инфраструктура за двете среди и да автоматизираме тестването ѝ.
Изводи
Работоспособността на основния възел на системата за съхранение на данни е една от основните задачи на екипа SRE и експлоатация. Внедрението на оркестратор и HA-решение на основата на VIP позволи да постигнем следните резултати:
- надеждно откриване на проблеми с топологията на кластера БД;
- автоматично и бързо реагиране на инциденти, свързани с майстора, което намалява времето на престой на системата.
Въпреки това, решението има свои ограничения и недостатъци:
- мащабирането на HA-схемата на няколко ЦОД-а ще изисква наличието на единна L2 мрежа между тях;
- преди да присвоим VIP на новия майстор, трябва да освободим същия на стария. Процесът е последователен, което увеличава времето за възстановяване;
- освобождаването на VIP изисква SSH достъп до сървъра или друг начин за извикване на отдалечени процедури. Тъй като сървърът или БД-то изпитват проблеми, довели до процеса на възстановяване, не можем да бъдем сигурни, че освобождаването на VIP ще завърши успешно. А това може да доведе до появата на два сървъра с един и същи виртуален IP адрес и проблем.
split brain.
За да избегнем split brain, можем да използваме метода („Убий другия възел в главата“), който напълно изолира или изключва проблемния възел. Съществуват и други начини за реализиране на висока наличност на кластера: комбинация от VIP и DNS, откритие на услуги и прокси-сервизи, синхронна репликация и други методи, които имат свои недостатъци и предимства.
Разказах за нашия подход към създаването на отказоустойчив кластер MySQL. Той е лесен за реализация и осигурява приемливо ниво на надеждност при текущите условия. С развитието на цялата система като цяло и инфраструктурата в частност, този подход несъмнено ще еволюира.
Източник: habr.com
