Pull to refresh

Comments 71

Каковы потери производительности, которые уходят на согласование запроса со всеми мастерами(режим-то синхронный)? Желательно в процентах и в секундах.
Соединены ли у Вас мастера в рамках ЛВС или через Интернет?
Кластер через интернет — очень плохая идея, не смотря на то что можно меня gmcast.segment=, проблемы будут. Этого делать не стоит. Разве что у Вас нет своей собственной оптики между ДЦ.
Потери производительности безусловно есть, но в секундах они не измеряются точно, это мс. В процентах — не представляю как это вывести. Просто, считайте что сеть должна быть железобетонная и сервера одинаковые или близкие по конфигурации дисков и процессора, тогда потери будут минимальные.
А если очень хочется? Между разными ДЦ в разных странах. Нагрузка небольшая, каналы относительно стабильны и как правило плавают в диапазоне от 200 до 800 мегабит на коннект. Хочется мультимастер для биллинга и подобных штук.

Каких стоит ожидать проблем?
По моим изысканиям всё упирается в RTT. Т.к. на каждый запрос(или коммит, точно не скажу) происходит согласование со всеми остальными мастерами, и когда они дадут согласие, тогда только сервер получивший запрос начнёт его выполнять. Посему маленький запрос на INSERT может вместо пары микросекунд выполняться до 200милисекунд из-за того что согласование произошло между серверами стоящими в России и Америке, например.

А ещё всё это становится более шатким, если Вы хотите как я иметь 5,6,7… мастеров.
Особенно плохо, когда связь периодически рвется или затрудняется.
Нужно держать разные участки кластера в разных gmcast.segment, тогда что то еще получится.
Подробнее стоит почитать о gmcast.segment в документации по galera 3
innodb_file_per_table = 1

это разве хороший выбор в плане производительности на больших базах?

При репликации подобной схемой, автоинкримент на мастерах не затрагивается auto_increment_increment?
Автоинкремент вычисляется автоматически, он равен числу членов кворума. Т.е. количество нод СУБД и арбиттраторов.

innodb_file_per_table=1 нужен как минимум, для нормальной работы xtrabackup.
Т.е. я правильно понимаю, что автоинкримент сквозной будет между мастерами, без пропусков? Не совсем понял механизм какой будет назначения primary key если я на двух серверах с потеряной связностью вставлю 100 записей в таблицу.
не будет коммита, если не будет коммита на всех нодах кворума. Так что ничего не сможет вставится при потере связанности. Нода без кворума переходит в точно для чтения или вообще закрывается.
насколько я знаю, это не так
по крайней мере было не так, когда я присматривадся galera
нет никакого синхронного коммита, каждый writeset проходит некую сертификацию, проверку на отсутствие конфликтов, и если она пройдена, транзакция считается закоммиченной на всех нодах, что будет по факту на каждой из нод — как повезет
что-то поменялось с тех пор?
А разве query_cache не рекомендуют отключать по той причине, что данные и так кешируются в буферном пуле innodb?
Нет его отключают совершенно по другой причине. Его не внедряли ранее, так как очень трудно согласовать кеш между всеми нодами и на первых порах это приводило к дедлоку по причине кеша. Те на одной ноде поменялась запись и значит кеш должен сбросится на всех. А допустим где то сервер под нагрузкой и кеш не сбрасывается и в итоге все ноды ждут сброса кеша на одной из нод. В итоге они напряглись и починили это. Теперь работает как часы, главное выполнять рекомендации.
innodb
Как я понимаю, главная проблема как раз в том что он однопоточный, такая себе критическая секция. Изначально создавался более похоже на хак чтобы ускорить работу не слишком быстрых на то время подсистем хранения. При вытеснении из кеша он лочится целиком, потому для систем с частыми вставками/обновлениями скорость выборок может существенно падать и создаваться затыки.
Похоже на то. К сожаления, раскопать, как они починили это в текущей реализации, мне пока что не удалось. Но факт — работает.
Вроде «раньше» советовали его вырубать по той причине, что однопоточный он. И вся мощь расшибалась лбом об мьютексы…
Но вроде в случае мастер-мастер это может быть не правдой, только как проверить?
опытным путем, так как это почти не документированная фича сейчас.
Не, там в другом проблема. То есть в мьютексах, конечно. В момент когда нужно его очистить, в случае, если содержимое таблиц, к которым обращаются хранящиеся в нём запросы, поменялось, он держит глобальный мьютекс и все остальные запросы стоят. Такое особенно заметно при высокой нагрузке и большом размере query cache. А пока он себя обновить не решил — всё многопоточно. Случай мастер-мастера здесь роли не играет. Его фиксили, но недофиксили: там с архитектурой какие-то проблемы. Поэтому лучше просто держать маленьким: 256 MB всяко быстрее обновится, чем 4G.
А зачем согласовывать (или синхронизировать) кеш? Как это влияет на работу кластера и целостность данных?
Возможен ведь вариант при котором с одной ноды будут читаться данные из одной таблицы, а на другой ноде будет чтение из других таблиц или например будет вестись только запись без чтения или чтения будет гораздо меньше.
И все же, зачем query_cache если бд в innodb?
Ну и для примера, допустим размер бд > 50 Гб, при этом активные данные составляют порядка 10%, при этом:
600 r/s — selects,
50 r/s — updates,
20 r/s — inserts,
20 r/s — delete.
Как здесь быть с query_cache и как лучше в этом случае кешировать активные данные?
Если не согласовать кеш то прочитав данные из другой ноды ты получишь уже не актуальные на данный момент.
Возможен любой вариант, это полноценный синхронный мульти-мастер. Во все ноды можно писать и читать одновременно.
в query_cache хранятся хеши запросов и ответы на них, в innodb копии страниц данных, с диска.
Те в одном случае результат в другом — исходные данные.
innodb должен быть как можно больше, так что бы вместить данные базы и не ходить за ними на диск.
query_cache должен быть минимально необходимым, до 512МБ максимум.
А можно позанудствовать чуть-чуть?

У Оракла нет имплементации Galera — это совершенно независимый от него продукт.
Federated была разработана ещё в MySQL AB и, к сожалению, до сих пор официально поддерживается. К сожалению, потому что если вы пойдёте на bugs.mysql.com и сравните как быстро устраняются баги, например, репликации и Federated — будет понятно что я имею в виду =)

> Стоит добавить важный с точки зрения производительности параметр skip-innodb_doublewrite

Он ещё самый важный с точки зрения сохранности данных
сохранность данных на диске конкретоной ноды, это не очень важный фактор. состояние будет передано при sst. а вот для ускорения работы кластера в целом, нужно минимизировать работу субд с диском до минимально необходимого
Действительно интересно, MariaDB берет у Percona ее xtradb движек, а Percona берет у MariaDB — galera-у.
Так в итоге galera ok? Просто сейчас стоит задача по кластеру, раньше работал только с percona так как galera была еще beta.

Еще тут в голове выросла такая схема, если можно покретекуйте.

два роутера с keepalived, 4 ip адреса. Два из них между машинами могут мигрировать в случаи отказа.
Там же HAProxy, доступ к нему по DNS-RR.
HAPRoxy уже к web,mysql итд.

Кстати пробовали ли IPVS вместо HAProxy?
лучше maxscale
но можно и haproxy.
Про maxscale не слышал, буду читать, спс. HAProxy просто уже знаком.
а разве изначально не Майкл Видениус — Monty Program AB?
Хм… Честно говоря я не помню как Galera начиналась =)
Спасибо за статью, очень интересный материал.

А насколько проблемно восстановление консистентности данных на всех узлах при выпадении одной из нод (скажем некий внеплановый ребут)? Каким образом осуществляется балансировка нагрузки в мульти мастер инстансах?
не сложно. Все происходит автоматически при запуске выпавшей ноды. Иногда нужно удалить все ее локальные данные и перезагрузить еще раз.
Различают 2 варианта передачи состояний. Полное и инкрементальное. При повреждении локальных данных или первом старте, будет происходить полный SST.
По балансировке — HAProxy или MaxScale. По первому, ссылка на статью в начале текста.
А можно подробнее про восстановление? Использую в продакшене два percona server в master-master репликации и любая перезагрузка одной из нод ведет к неизбежному геморою при восстановлении.

Касательно HAProxy — при алгоритме с последовательным распределением запросов на ноды рано или поздно sql репликация может перестать успевать за балансировщиком и появляются duplicate entry. Как вы этого избегаете?

Использую в связке с zabbix, поэтому особенно интересно :)
Ну класика же! Попробуйте использовать 3 ноды для кворума, при двух непонятно кто живой и кто прав.
Правда когда я использовал 3 ноды, возникали вопросы с записью. См ниже.
Обязательно попробую, пока надо придумать как это сделать максимально безболезненно)
никакого гемороя не будет. Важно понимать что, 2 ноды это мало. нужно как минимум 2 и абраттратор. А лучше 3 или 4.
Записывать нужно в один сервер или по крайней мере, что бы набор баз и таблиц в которую ведется запись была разной.
MaxScale умеет отправлять запись в один набор нод а чтение в другой. Причем на уровне запросов а не соединений.
Круто, спасибо.
Тогда если не затруднит, ещё пара вопросов:
1. Умеет ли maxscale работу с двумя нодами (как в моем случае)?
2. Есть ли рецепты по максимально безопасному и бастрому переезду с multi master схемы на кластер? И насколько мощным должен быть арбитратор?

А то потихоньку подходим к необходимости масштабироваться:
image
Арбитратор это минимально мощный сервер.
что у вас за мульти-мастер?
2 инстанса percona server 5.6 с настроенной master-master репликацией расположенные на виртуалках с 8ядрами и 16гб оперативки + ucarp (т.е. по сути запись и чтение ведется только с одной ноды, вторая для горячего переключения в случае крэша).
я не совсем понимаю как мастер-мастер? перекресная репликация?
Да, классическая перекрестная репликация.
ой. это жесть)
просто удаляешь оба инстанса и ставишь галеру. плюс арбиттратор.
ну и mysql_upgrade --force
а чем будет лучше два машины + арбитратор, чем например три машины в кластере?
Что будет если арбитратор выйдет из строя?
Еще непонятно почему арбитр должен быть мощным? Он же просто вроде как принимает роль, кто остается работать в случаи фрагментации.

Лучше 4 сервера в кластере, но если нужно сократить число серверов к минимуму и экономить их мощность. То можно использовать слабый сервер, как арбиттратор.
Не надо 4 сервера. Чуть ниже я описал почему.
Всем спасибо за ответы, за советы, а SyCraft ещё и за отличную статью!
А лучше 3 или 4
не стоит… Лучше, это когда число голосов (ноды+арбитраторы) нечётное, иначе splitbrain более вероятен. Хотя это зависит от конкретной схемы включения, тем не менее нечётное число всегда предпочтительней.
Почему? откуда такие рекомендации, где почитать?.. Рекомендация лишь одна — нод должно быть более 2. А дальше без ограничений.
Что значит где почитать? Что по Вашему такое splitbrain и почему он происходит?
Попробую найти где-нить строки хоть в чей-нибудь документации… Где-то явно оно есть.

Тут указано про минимум 3 сервера, но они явно упустили момент с чётным числом узлов.
splitbrain возможен когда ноды теряют согласование транзакций, так как они не знаю какая имеет верное состояние в данных момент. Это возможно, лишь когда нод 2. Все что выше, за счет других нод или арбитратторов, это кворум и splitbrain не может быть. Хоть четное их чесло, хоть нет. Речь ведь о Galera?
Речь о любом кластерном решении и Galera не исключение. Если у Вас будет кластер из 4-х нод, то в качестве необходимого для кворума, сколько нод Вы укажите? А теперь предположим что кластер развалился пополам. Если в качестве кворума было указано:
2 ноды — то каждая половина решит что она главная и будет существовать независимо. Вот и коллизия данных.
3 ноды — кластер просто перестанет существовать, т.к. каждая половина решит что её мало.

Вот у percona есть про это, нашёл.
я не буду указывать число нод в кворуме. Он будет выбирать это самостоятельно. Почему кластер должен развалится пополам? Если будет 4 ноды и они развалятся пополам, то будет 2 ноды по 2. Как вы сами и сказали, оба этих кластера не будут жизнеспособными.
Я бы еще согласился если бы нод было 5,6 или более.
Если число голосующих узлов будет нечётным, то не будет ситуации когда кластер развалится на две ЛЮБЫЕ части и при этом перестанет функционировать. И нету ни какой разницы произойдёт это при 2,4 или 6 узлах. Суть проблемы не меняется.

Если Вы считаете что конкретно Ваша инсталяция в силу расположения или схемы включения не способна развалиться на 2 половины, то наш разговор я считаю без полезным. Всё остальное я уже описал выше.
я уже выше написал, что не стоит делать кластер через интернет) думаю на этом уже стоило закончить.
Полагаться на одну локацию не комильфо.
Я не знаю как сейчас, но раньше можно было задать вес арбитру (ArbitrationRank).
0 — не станет арбитром, 1 — станет арбитром с высоким приоритетом; 2 — нода станет арбитром только если нет претендентов с высоким приритетом.
Как раз очень удобно когда у вас появлялось 4 машины. Еще я тут свои заметки полистал, арбитром вроде бы становилась одна из нод? Т.е это машина так же может заниматься хранением данных или это можно вынести отдельно как управляющию ноду?
Арбиттратор это служба galera без mysql )
те она просто поддерживает кворум, следит за порядком коммитов и составом участников. равнозначный член кластера без данных.
Еще хотел спросить, раньше была рекомендация писать в 1 ноду, иначе можно получить cluster-wide deadlocks.
www.percona.com/blog/2012/08/17/percona-xtradb-cluster-multi-node-writing-and-unexpected-deadlocks/
Это так же актуально?

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

Пример:

NODE1
[mysqld_safe]
wsrep_urls=gcomm://192.168.0.16:4567,gcomm://192.168.0.17:4567

NODE2
[mysqld_safe]
wsrep_urls=gcomm://192.168.0.15:4567

[mysqld]
bind-address=192.168.0.16
wsrep_node_name=node16
wsrep_sst_donor=node15

NODE3
[mysqld_safe]
wsrep_urls=gcomm://192.168.0.15:4567

[mysqld]
bind-address=192.168.0.17
wsrep_node_name=node17
wsrep_sst_donor=node15

Так же надо было отдельно инициализировать кластер пустой строкой gcomm://.

Это все еще актуально, или вопрос как то решается по другому?
P.S. Пишу как из каменного века :)

P.P.S.
www.percona.com/doc/percona-xtradb-cluster/5.5/howtos/3nodesec2.html
Раньше использовал.
Я выше ответил про cluster-wide deadlocks,
так же там в параметрах есть тот, который отвечает за ретраи дедлока. Проблема решается при использовании maxscale.
в заготовках для всех конфинах меняется только адрес ноды, имя ноды и список существущих нод. Текущая всегда будет последней в списке wsrep_urls
Инициировать кластер пустой gcomm:// до сих пор нужно)
<в заготовках для всех конфинах меняется только адрес ноды, имя ноды и список существущих нод. Текущая всегда будет последней в списке wsrep_urls

Что значит текущая? Речь идет о 1 ноде? Вроде бы как в wsrep_urls мы просто перечисляем список всех нод или нет?
На других нодах мы пишет адрес первой ноды (да собственно пример выше) или я как то вас не пойму?

Можно все же пример?
первая, ее адрес 192.168.0.76
wsrep_cluster_address = gcomm://192.168.0.30,192.168.0.40,192.168.0.41,192.168.0.74,192.168.0.75,192.168.0.76

вторая, ее адрес 192.168.0.75
wsrep_cluster_address = gcomm://192.168.0.30,192.168.0.40,192.168.0.41,192.168.0.74,192.168.0.76,192.168.0.75

третья, ее адрес 192.168.0.74
wsrep_cluster_address = gcomm://192.168.0.30,192.168.0.40,192.168.0.41,192.168.0.76,192.168.0.75,192.168.0.74
итд
Я бы поставил innodb_locks_unsafe_for_binlog=false чтобы режим REPEATABLE-READ нормально работал. А также поставил бы innodb_flush_log_at_trx_commit=0.
innodb_flush_log_at_trx_commit=0 это перебор как мне кажется. innodb_locks_unsafe_for_binlog устарел уже в 5.6/10, но почему лучше в 0? что бы избежать фантомного чтения?
Насчет innodb_flush_log_at_trx_commit=0 может и перебор, если в датацентре свет отключат. А насчет innodb_locks_unsafe_for_binlog всё верно. Я конечно понимаю, что REPEATABLE-READ ведет к дедлокам и тормозам, но, блин, это так удобно, это как SERIALIZABLE в PostgreSQL.
Поясни почему. В MSSQL и Oracle этот режим по умолчанию, кроме того, так же как и в oracle, между снимками работает согласованное чтение. В чем минус?
Ты имеешь ввиду READ-COMMITTED по-умолчанию? При READ-COMMITTED мы можем прочитать данные согласовано только в пределах одного SQL запроса. А если запроса два — то между ними другая транзакция может навтыкать данные. И к каким последствиям это может привести — тяжело предсказать. Например в первом запросе извлек айдишники, а во втором запросе пытаешься подтянуть по ним данные (типа такой программный join осуществляешь). И всё, бабах. По некоторым айдишникам ниче не подтянулось, NullPointerException. Кто-то удалили эти записи между запросами. Придется предусматривать в коде этот случай.
READ COMMITTED Нечто похожее на уровень изоляции Oracle. Все выражения SELECT… FOR UPDATE и SELECT… LOCK IN SHARE MODE блокируют только индексные записи и не блокируют интервал перед ними. Поэтому они позволяют свободно добавлять новые записи после заблокированных. UPDATE и DELETE, которые используют уникальный индекс и уникальные условия поиска, блокируют только найденную индексную запись, и не блокируют интервал перед ней. Но в UPDATE и DELETE диапазонного типа в InnoDB должны установить блокировку следующего ключа или интервальную блокировку и блокировать добавления другими пользователями в интервал, покрытый диапазоном. Это необходимо, т.к. «фантомные строки» должны быть блокированы для успешной работы репликации и восстановления в MySQL. Согласованное чтение работает как и в Oracle: каждое согласованное чтение, даже внутри одной транзакции, устанавливает и читает свой собственный снимок.
Я бы поставил innodb_locks_unsafe_for_binlog=false чтобы режим REPEATABLE-READ нормально работал. А также поставил бы innodb_flush_log_at_trx_commit=0.
Sign up to leave a comment.

Articles