Pull to refresh

Comments 82

Работоспособность сервисов лучше делать не с помощью telnet, а делать нормальные подключеня. Если, например, web-сервер установил соединение, это совсем не значит, что он корректно работает. Какой-нибудь Nagios Вам в помощь.

PS: в [ (man test) есть -a (И) -o (ИЛИ), не нужно делать if в if
Про нагиос знаю, возможно потом прикручу некоторые скрипты оттуда.
if в if — привычка с универа.
В продолжение комментария. Касательно, например, mysql. Порт может и прослушивать, но репликация может развалиться. И вам будет казаться что все хорошо, но давным давно не так радостно.

У себя на текущий момент используем Percona XtraDB Cluster. Там есть замечательная утилита clustercheck, которая проверяет не только доступность сервиса в принципе, но и, что самое главное, синхронизированность ноды.
А я для обычного MyISAM master-slave парсю вывод show slave status.
Также, есть скрипт, который быстро восстанавливает репликацию в случае падения (ручками это ой как не быстро, и последовательность действий не всегда с ходу вспомнишь).
Percona XtraDB Cluster используется в режиме Мастер-Мастер?
Да, синхронная master-master репликация. Используется три ноды.
в кольце?
как с производительностью?
может ли сломаться репликация и какие могут быть подводные камни?
По сути — в кольце, будем называть это так.

Касательно производительности. Мы производили тестирование под конкретные свои приложения. Получили приблизительно следующее: при чтении информации — производительность аналогична отдельно стоящему mysql серверу (это производительность одной ноды, а учитывая то, что запросы балансируются между тремя серверами, между сказать что деньги и силы потрачены не только на повышенную доступность, но и производительность), при записи информации — падение производительность в 5-7 раз. Да, с одной стороны падение существенное, но мы понимаем на что идем и чего стоит синхронная репликация. А учитывая соотношение чтение/запись как 95/5 — для себя считаем приемлемым результатом.

Может ли сломаться репликация? В принципе может, в продакшене такого не было, но лабораторных условиях когда мы «насиловали» кластер — такое получалось. Если это и происходило, то совсем не там где мы ожидали. В частности, есть базовые методы трансфера: rsync и xtrabackup. Соответственно первый — блокирующий базу на запись, второй нет. Интересно то, что с rsync проблем не было, если на что-то и натыкались, то с xtrabackup. И что еще интереснее, отпад ноды происходил не во время нагрузочных или иных тестов, а чаще в режиме штатной работы. Пусть это и не научно, но проблема бывало как появлялась так и пропадала (при том что куча аналогичных примеров есть у других пользователей и рекомендуемые меры не очень уж и помогали). Где-то делаем ссылку на сыроватость под конкретную платформу, потому как проблемы с xtrabackup чаще всего встречаются у людей с Debian 6 x64. Повторюсь, что все касалось только xtrabackup.

Отмечу также немного слабоватый официальный форум, а-ля покупайте фирменный суппорт.
место общения community — google группы, а там 90% шлака.

По крайней мере для себя многое что отловили, проверили, получили некую базу знаний и сценарии действия в тех или иных ситуациях. На последок скажу, репликация синхронная, но если на уровне приложения Вы можете реализовать балансировку чтение/запись — делайте, это Вам +1 к крепкому сну.
1. Master-Master может не выжить под нагрузкой
2. Держать MySQL и HTTP сервера на одной железке это очень большая нагрузка на диск (ну если конечно сервис не посещает полтора землекопа в сутки). И это печалька

Добавление в решение даже слабенького сервера с nginx/haproxy/lvs в качестве балансера будет более правильным, как мне кажется. Да и статику я бы вынес на него тоже
при 4 серверах делаем так:
— 2 сервера со статикой как балансировочники на Frontend с NGinx
— 2 сервера под MySQL с Apache
Но из 2х имеющихся я сделал как описано выше…
при 4 серверах делаем так:
— 2 сервера со статикой как балансировочники на Frontend с NGinx
— 2 сервера под MySQL с Apache
Но из 2х имеющихся я сделал как описано выше…
на 6-ти mysql выносить на третью пару? Ну, ОК! Только мне все равно кажется что master-master не очень
Держать MySQL и HTTP сервера на одной железке это очень большая нагрузка на диск (ну если конечно сервис не посещает полтора землекопа в сутки). И это печалька


Это как-то не о чем. Mysql, http сервера и диски бывают очень разными. Также как и сами движки сайтов…
Дело в том, что MYSQL дает совсем другой тип нагрузки на диск нежели отдача «мелочи» по http. При хорошей нагрузке — всё в любом случае упрется в диск, но тут одно но: лучше распределить отдачу мелочи (которая еще и осядет в кешах FS) на один сервер, а большие выборки и частые записи (если оно активно пополняется — а это типичная задача типа форума) на другой. Проживет под нагрузкой значительно дольше, да и работать будет быстрее.
Для синхронизации файлов лучше использовать lsyncd, а не строить велосипед на скриптах и unison
пожалуй лучше вынести зоны dns на хостинг и обновлять через nsupdate.
А для контроля сервисов я использую munin. Через подобную связку, как у автора, я уже прошел. Сейчас стараюсь все сделать на уровне тех или иных демонов.
А в БД есть автоинкрементные поля? Советую тогда еще настроить параметры mysql auto_increment_offset и auto_increment_increment. Например на сервере №1 auto_increment_offset = 1, на втором — auto_increment_offset = 2. auto_increment_increment = 10 на обоих серверах. Тогда ваши ключи никогда не пересекутся. Потому что даже если вы не модифицируете БД на двух серверах одновременно, из-за сбоев или задержки репликации может вылезти ситуация, когда на обоих серверах заинсертятся записи с одинаковым id. В таком случае репликация остановится, и БД будет некорректной.
Думаю надо это добавить, лишним не будет, а в случае чего данные не потеряются. Спасибо!
В вашем случае можно auto_increment_increment = 2 сделать, но я обычно делаю 10. Тогда четко по id видно, на каком сервере он создан. Если заканчивается на 1 — первый сервер, на 2 — второй. У нас такая схема работает уже несколько лет, полет нормальный. При чем у нас два сервера используются одновременно.
А если обращения по ID полям, которое автоинкрементно, идут, то, как я понимаю, будут не верные данные выдаваться на одном из серверов?

У меня просто паранойя небольшая в этом плане есть…
Можете подсказать способ проверить это, чтобы убедиться, что прямых обращений к ID полям нет?
Не совсем понял вопрос… Прямые обращения — т.е. инсерт с явным значением ID? Данные будут одинаковыми на обоих серверах. Но вы должны сгенерить такой ID, чтобы он был уникальным в пределах двух серверов, т.е. чтобы в этот же момент времени на втором сервере не произошел инсерт с таким же ID. Иначе происходит ошибка dublicate key — и привет, репликация останавливается.

Вообще, если репликация работает, то на обоих серверах будут одинаковые данные. Соответственно выдаваться они тоже будут одинаково. Значения auto_increment_increment и auto_increment_offset влияют только на генерацию autoincrement ID. У вас в базе будут такие ID например:
1
2
11
21
22
32
31
Все что заканчивается на 1 — добавлено на сервере №1. Все что на 2 — на сервере №2. Но данные одинаковые на обоих серверах (при активной репликации). Если даже у вас репликация остановится, и оба сервера будут параллельно работать и инсертить данные, то когда репликация поднимется, данные корректно засинхронизируются.
ЗЫ.
> чтобы он был уникальным в пределах двух серверов
Я бы даже сказал, ID должен быть уникальным и как-то зависеть от текущего сервера, чтобы такой ID никогда не мог быть сгенерен на другом сервере.
У меня, как я заметил, не инсерты, а селекты, в которых явно прописан ID (там, на сколько я знаю, данные ручками вбивали в БД (это было за долго до меня)). Теперь понятно стало, спасибо.

ошибка dublicate key

У меня эта ошибка была когда я настраивал репликацию master-slave для Битрикса. Получается, что мне надо было прописать auto_increment_increment и auto_increment_offset?
Если в селектах явно прописан ID (прямо в коде, я так понимаю) — то это вообще неправильно и странно.
По идее при master-slave можно не менять дефолтные значения auto_increment_increment и auto_increment_offset. По дефолту они = 1.

А ошибка dublicate key могла возникнуть если у вас уже были какие-то данные с ID, указанными вручную, а потом вы начали использовать autoincrement. В таком случае надо просто в auto_increment_offset установить какое-то большое число (больше чем MAX(ID)). И дальше инсерты автоинкрементных ID пойдут без ошибок.
ЗЫ. Ну и конечно же на слейве нельзя делать никаких модифицирующих запросов.

Вообще, как показывает практика, лучше настроить master-master как я описал выше, чем например иметь master-slave и в случае падения мастера, переводить слейв как бы в режим мастера. Если у вас именно такой master-slave, то auto_increment_increment и auto_increment_offset тоже лучше настроить так же как я писал выше для мастер-мастера.
Да, прямо в коде было. Но там, где нашел, я сразу же исправил. Знаю, что это тот еще костыль. (задолго до меня делали)

Я когда реплику настраивал развернул новый чистый сервер, поставил все что надо, потом сделал дам базы на мастере и залил его на слейв. По началу все было ок. Но когда утром народ начинал заходить на сайт и работать, то начинали сыпаться ошибки дубликатов. Хотя на слейв они не могли писать (не было настроено доменное имя, dns и все такое).
В понедельник попробую реализовать мастер-мастер, с учетом ваших советов и статьи.

Спасибо большое за развернутые ответы и статью.
то что у обоих серверов одинаковый server_id в my.conf — это бага или фича?
Это бага, Спасибо! Исправил :)
Такой вопрос. Медиа контент между сайтами синхронизируется раз в 5 минут. Получается что если добавляется новый материал, но на протяжении 5 минут есть вероятность получить 404 при попадании на другой сервер.
да, все верно. Можно уменьшить время синхронизации, защита от запуска нескольких процессов синхронизации предусмотрена.
а можно медиа контент запихать на фронтэнд, отдавать напрямую, а класть с беков по nfs (ведь добавлять его приходится минимум раз в 10 реже, чем отдавать)
Не готов сказать как можно это подкрутить с помощью apache, но при использовании nginx есть замечательная директива try_files. С ней эта проблема снимается и как следствие, можно делать контрольную синхронизацию медиа контента реже (например раз в несколько часов), потому как сервера сами себя «отсинхронизируют» (происходит не запрос не существующего фала и его локальное сохранение).
Ну кстати да. try_files и проброс на следующий бекэнд.
Что-бы не переписывать ДНС — делаете две ns записи, одна указывает на первый сервер, вторая на второй. Первый должен отдавать в А записи только свой ip, второй свой. Если один из серверов отпадет — соотв. не будет и его записи.
Хороший вариант. Добавлю только то, что особо колдовать с DNS смысла нет. Современные браузеры автоматически распознают не работающий сервис и переключаются на другой IP адрес.
Моя идея не в балансировке, а в резервировании и отказоустойчивости, поэтому перезапись ДНС — способ, которым я это достигаю.
Я бы все же использовал две днс записи, и не делал перезаписи.

Просто записи ДНС могут расползатся в течении 24 часов, ну и какая тут отказоустойчивость?

Потом вопрос про mysql и master — master, можно сказать из класики.
Если падает между ними линк, то если мне не изменяет память они сразу становятся slave. В общем явно нужна еще одна машина.

Рекомендую mysql заменить на percona.
Почитать и посмотреть о Pacemaker.

как вариант с 3 машинами, можно было бы поднять и ceph как блочное устройство с gfs2 для файлов apache.
Правда там другие сложности, которые надо будет решать.
про mysql master-master читал тут: Ссылка
По поводу
Просто записи ДНС могут расползатся в течении 24 часов, ну и какая тут отказоустойчивость?

Я как раз в настройках зоны и указываю интервал обновления 10 секунд…
Ну там как раз и описанны проблемы.

>использовать асинхронный Master-Master для одновременной записи в обе БД без знания подводных камней — опасно и ненадежно и применяется в редких кейсах.

На тему ДНС, не все так просто и не всегда зависит от выстовленного TTL у вас.
По пути как не странно могу попасть разные кэши, которые могут игнорировать, что вы написали. Да и машина простаивает просто так :)
Я использую мастер-мастер для записи в обе БД. Все ок.
Когда использовал master-slave, были проблемы. Например когда мастер падал, и мне надо было перевести слейв в режим мастера.
ЗЫ. Главный подводный камень — не стоит использовать функции вроде NOW(), RAND(). А также апдейты с LIMIT в конце. Такие операции могут выполняться на каждом сервере по-разному.
Я очень рад за вас, что вы пока еще серьезно не наступили на грабли master-master.
> По пути как не странно могу попасть разные кэши, которые могут игнорировать, что вы написали.

сколько работаю с такой схемой ни разу не встречал. пример в студию таких DNS-кешей, которые меняют или игнорируют TTL. очень хочу посмотреть им в глаза.

ест варианты, когда клиентское ПО кеширует вычисленный ИП. с таким сталкивались, да, но с DNS проблем не было.
Любой кэширующий днс.

PDNSD,dnsmaq,unibound — в той или иной степени могут нарушать правила работы с ttl.

и не надо использовать scp. Есть ssh-copy-id:

ssh-copy-id username@host
А еще синхронизация фалом можно делать при помощи GlusterFS, настаривается не сложно, и не надо никаких подпорок в виде скриптов.
Что, и под x86_86 уже есть клиент? А то бывает не у всех x64.
Да, и не у всех linux =)
Нет, ну конечно я имею в виду сервера на Linux, автор же использовал толькор Linux. О построении подобной схемы под Windows я понятия не имею.
прямого клиента нет, наверно через fuse можно.
Если надо думать о шаре можно извратится так

Поднимаем ceph, поднимаем машину с linux — настраиваем samba.
Второй вариант, поднимаем виртуальную машину и ceph выступает как блочное устройство.
GlusterFS в базовой поставке умеет шарить данные по NFS через FUSE, даже не нужно ничего дополнительно доставлять. Windows 2008/2012 тоже умеют NFS из коробки., насчет десктопных версий не знаю.
GlusterFS да знаю что умеет. Для Windows надо ставить отдельный пакет, если не изменяет память.

Потом GlusterFS умеет и CIFS если мне не изменяет память, правда я не знаю в каком оно состоянии.

Ну а NFS реализация 3 версии, что не совсем интересно.
>настаривается не сложно

как то не осилил по быстрому, может быть будет время напишите статью?
Да, конечно, напишу, как только появится время.
GlusterFS как-нибудь снижает производительность?
Как он отрабатывает исключительные ситуации, например между нодами разрыв сети, и создали 2 разных файла по содержанию, но одинаковые по имени, а потом связь восстановилась?
Glusterfs как и ceph надо тестировать под ваши нужды.
Мне показалось, что ceph более живучий.

Когда кластер разваливается, то работают стандартные правила для кластеров. Кого больше, тот и прав :)
Чтобы сделать автоматическую синхронизацию раз в 5 минут, необходимо использовать следующий скрипт:

В локинге у вас race condition. man flock:
       (
         flock -n 9 || exit 1
         # ... commands executed under lock ...
       ) 9>/var/lock/mylockfile
Что будет при разделении сети? То есть серверы друг друга не видят, но некоторым клиентам удаётся соединиться, причем к обоим серверам.
Добавив различия для автоинкрементов, как посоветовали ранее, все запросы будут обрабатываться нормально, когда связь появится, то данные синхронизируются между серверами без ошибок.
Также, при такой ситуации будет уведомлен админ, который начнет решать данную проблему. Сообщение на почту придет от обоих серверов.
Разве что у вас нет ни одного апдейта. Данная архитектура не может быть полностью отказоустойчивой.
Не совсем понимаю о чем Вы, можете пример привести?
предположим некий сайт. человек оставил коммент. потом произошло разделение сети. человек изменил свой коммент. обновил страничку. попал на другой сервер. увидел неизменённый коммент. снова изменил, но по другому, написав про беспредел админов, запрещающих редактировать коммент. сеть восстановилась. Какие изменения будут в общей копии?
Если на разных серверах обновить одну и ту же запись разными значениями, то серверы так просто не синхронизируются. Чтобы такого не было, надо непарное количество серверов, тогда каждый сервер будет знать, находится он в большей части повреждённого кластера или в меньшей. Если в меньшей, то он перестаёт принимать запросы. Другой вариант — база может в любой момент вернуть несколько версий документа, и пусть приложение решает как обьеденить их. Так сделано в Amazon Dynamo и Riak, для MySql, конечно, не подойдёт.
>надо непарное количество серверов

не совсем верно :) У нас могут и три сервера потерять связь друг с другом. Если бы было 4, то все было бы ок.
Ну и по возрастающий.
3-х серверный кластер может выдержать сбой одного сервера. Если все три потеряли связь, то ни один работать не будет, так как нужен кворум. А с 4-мя серверами кворума нет, но можно одному из них дать дополнительный голос. Это касается автоматического режима. Но если произошел сбой большей части кластера, то можно еще вручную указать какому-то серверу продолжать работать, это тоже будет безопасно для данных.
С 4-мя чуть не так, кворум то есть, но он достижим при том же количестве упавших нод, что и с 3-мя. То есть преимущества нет. Но если одному дать дополнительный голос, то кластер выдержит сбой от 1 до 2-х нод. Кластер не может выдержать сбой серверов в количестве большем или равным половине серверов, так как невозможно изнутри узнать причину сбоя — сеть или питание.
при некорректной перезагрузке сервера(например по питанию, либо в случае сбоя железа) репликация мускула с высокой вероятностью разваливается. поэтому Вы рискуете однажды утром проснуться, и получить в лучшем случае 2 независимых сайта(упал мастер, народ оставил комменты, залил файло на слейв, мастер поднялся, реплику данных не получил), в худшем неработоспособное приложение(во время отсутствующего мастера файлы со слейва удалили, записи на них в базе потерлись. мастер поднялся, изменения файлов со слейва подтянулись, базы нет)
UFO just landed and posted this here
Это не спасет от геморроя, лучше найти силы и поставить еще 1 один сервер и сделать кольцо.
Оно нормально работает на percona, в отличии от mysql. Ну и надо помнить, что mysql так и остался асинхронным.
Правда тут еще надо думать о балансировщики.
UFO just landed and posted this here
UFO just landed and posted this here
3 недели, сбоев не было. На тестах тоже не выявили проблем…
UFO just landed and posted this here
1. отказоустойчивая DNS балансировка, когда каждый сервер отдает только себя, имея в себе только одну NS запись, указывающую на себя. тем самым достигается отказоустойчивость при отказе серверов или потеря соединения с ДЦ. у регистратора прописываются NS записи, указываюшие на пул фронтов, тогда при отказе сервера или плановом ТО, при TTL 60 сек, можно спокойно отключать сервер и не париться о клиентах.
2. синхронизацию статики делать на nginx, когда он не находит файл и хочет отдать 404, то лезть за файлом на соседний сервер и сохранять к себе. никаких телодвижений больше делать не надо. штатная ситуация.
3. MySQL в отказоуйстойчивых системах в режиме master-slave не очень хорошее решение. нужна масштабируемая БД с мультимастером.

===

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

архитектура приложения это не выбор веб сервера или БД или конфигурации сервера, это уже более низкий уровень. архитектура приложения, тем более отказоустойчивого, это в первую очередь архитектура данных, которыми надо уметь управлять так, что бы данные были изолированы друг от друга и выход одной части данных не вел к общему краху системы. это денормализация, размещение разных данных в разных хранилищах, объединение данных с споты с миграцией по нодам.

разнести сервис по двум ДЦ и сделать мастер-слейв это вырыть себе могилу.

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

в данной архитектуре нет и намека на горизонтальную масштабируемость. нет ни слова о том, что если система будет испытывать затыки в нагрузке, то мы «втыкаем новые сервера, мигрируем часть данных на них и размазываем нагрузку».

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

===

хотите отказоустойчивую архитектуру 24/7?

1. горизонтальное линейное масштабирование путем увеличения кол-ва серверов с размазыванием/миграцией данных и нагрузки. возрос нагруз. воткнули пару серверов. перелили часть данных и все. без переписывания кода. просто клонируя ноды.
2. уровень кеширования, где кешируется все, что возможно. без кеша попасть под тяжелые запросы очень просто и это намертво кладет любой 24/7.
3. объединение данных в споты с миграцией по нодам.
4. полный мониторинг системы, изначально заложенный и продуманный. повторюсь. изначально, т.е. мониторинг это часть архитектуры, а не при бамбас для красоты.
5. прогнозирование нагрузки и понимание ее увеличения и решения этих проблем.
6. простая схема БД. линейные выборки. только простой SELECT. только хардкор. избавляться от JOIN, агрегируя данные уже в приложении.
7. посмотреь на данные. может часть положить в другие БД.

===

в общем прежде чем писать код, выбирать ДЦ(немцы\наши), сервера(ядра\память\винты\рейды), фронты(nginx\apache), бакенды(php\python\ruby\C\basic\asm), БД(mysql\pg\percona\mongo\hadoop), сесть, выпить и долго и нудно продумать архитектуру системы и данных, потому, что при продуманной архитектуре на самом дерьмовом говнокоде и дешевых серверах. все будет летать и любой напряг будет решаться в сотни раз быстрее, чем начнется рефакторинг, пачи, багфиксы, переделка схемы БД и прочая хрень, которая не даст сосредоточиться на самом главном: сиськи!
и в конце концов:

1. продумать схему данных и их хранение. что будет, если записей будет 1? 100? миллион? 100 лимонов? как смаштабироваться и перераспределить данные?
2. продумать мониторинг данных. их рост. отметить ключевые параметры роста.
3. продумать кеширование. что будет когда кеш вырастет? в10 раз? в 100 раз? как смаштабироваться?
4. продумать мониторинг кеша. как минимум соотношение попадания и молока, рост памяти.
5. продумать и выбрать бакенд(язык кодирования), позволяющий быстро вносить правки и производить выкладки. как смаштабироваться?
6. продумать мониторинг бакендов и отметить точки роста нагрузки.
7. продумать и выбрать фронты.
8. мониторинг фронтов и точки роста нагрузки. что будет если придет 100 запросов? 1000? лимон? как смаштабироваться?
9. мониторинг общей нагрузки системы. число данных(юзеры/товары/сообщения)
10. бекапы
11. бекапы
12. бекапы
13, тьфу-тьфу-тьфу
14. ну вот теперь можно и блек-джек…
Вот почему я так не умаю доходчиво объяснять :)?
Про мониторин; продумать мониторинг мониторинга :) Без шуток.
Sign up to leave a comment.

Articles