Как стать автором
Обновить

Комментарии 23

Подскажите, rps по WCF по своим метрикам на графиках или есть из коробки?
Пытался понять, как это вывести для http-rest запросов из коробки, не понял…
Все метрики у нас свои, встроены в код через prometheus-агенты, которые есть для всех основных языков. На самих WCF у нас сделана рест-дырка, а на стороне java-сервиса используется Apache http client, подсчитать запросы которого обычным Counter от Prometheus не составляет труда.
Сразу после этого тарантул слэйв начинает принимать запросы на изменение данных, в результате этого репликация с мастера разваливается, и мы получаем неконсистентные данные.

А разве слейв не должен возвращать ошибку при попытке записать? Он ведь знает что он не мастер.

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

По вашему описанию у кластера тарантула всё хорошо, это у одного из клиентов связь до мастера пропала. Что-то не понимаю тогда почему и в какой момент разваливается репликация у тарантула.

Всё правильно, им хорошо, они оба стали независимыми инстансами без репликации. Так как один из сервисов начал писать на слэйв, а слэйву ничего не мешает принимать запросы на добавление данных (больше того, так и было задумано), но возникают ошибки репликации, которые мы видим в логах ядра, после чего репликация разваливается. Ошибок именно на запись данных в lua-коде я не наблюдал, сервисы просто становятся назависимыми и продолжают работу.
слэйву ничего не мешает принимать запросы на добавление данных

Вроде как у реплик должно свойство read_only быть в true.

Тоже верно, но нам нужно, чтобы реплика становилась мастером, а делает это она, когда начинает принимать запросы на запись снаружи, как и было запланировано )

А почему клиенты решают, кто будет мастером? Это же должен делать сам тарантул на основе какого-то консенсуса о состоянии нод. Ну а если ни на стороне тарантула, ни на стороне клиента нет консенсуса о том, кто мастер, то очевидно при split-brain будет твориться всякая хрень.

А что делать приложению, которому надо работать, но база отвалилась? У него есть резервный адрес, куда можно ходить, и он туда идёт. Оно не знает, мастер там или не мастер.

Вспоминать CAP теорему). У вас не получится сделать консистентную и высокодоступную БД, которая не ломается от split brain.
Можно конечно повышать надежность сети как предложили ниже и надеяться что она не сломается — для неважных данных типа сессий это вполне решение. Но важные данные я бы не стал так хранить.

Соглашусь, пожалуй. А для важных данных другие требования и другие решения нужны. Здесь важна в первую очередь скорость. Если бы надежность стояла на первом месте, я бы смотрел куда-нибудь в сторону кассандры, например, с фактором репликации 2 или 3.
Допустим, конфликты репликации я порешаю, но они — это следствие проблемы, а не причина. Один сервис так и будет писать в первый тарантул, а второй — в другой. Слэйв будет иметь все данные мастера, но мастер данных слэйва всё равно не получит.
Вообще у тарантула есть мастер-мастер репликация. А слейву на самом деле нужно выставить read_only что бы при попытке записи в тарантул, тарантул возвращал ошибку и отправить вам алерт как минимум.
Но с мастер-мастер репликацией нужно быть аккуратным, так как словить duplicate primary key можно очень легко.
А так вам нужна некая промежуточная технология которая будет говорить вашим бэкендам кто сейчас мастер, тот же haproxy с неким чеком можно
То есть будет схема
Бэкенд — то что вы выбрали, выдало вам адрес текущего мастера — тарантул
Таким образом у всех бэкендов будет всегда один и тот же мастер.
Кстати если что, для haproxy тут есть пример как проверять доступность
Включал я мастер-мастер, когда идёт по 300 запросов в секунду, не успевает она. Особенно фигово, когда репликация разваливается, очень сложно потом хоть что-то поднять. Haproxy в работе использую, но не в данном случае. Может быть, стоит поэкспериментировать.
Обычно, когда требуется быстро решить проблемы с производительностью в legacy-приложении, по-быстрому прикручивают какой-нибудь кэш (пусть будет redis).
И после этого начинают потихоньку распиливать legacy на кусочки. А в кусочках уже используют все что считают полезным — очереди, хитрые стратегии распределения нагрузки, in-memory db и прочее.

По вашей схеме работы видится два решения, которые могли бы помочь избежать проблем потери связи между node 1 и node 4.
1) Повышение отказоустойчивости самой сети между нодами с использованием агрегации физических интерфейсов серверов например по LACP и/или FSN (fail safe network) и т.п. С линками между нодами, поключенными в том числе через разные физические Ethernet свитчи, пусть даже и стекированные. Главное что бы потеря любого физического линка или целиком свитча не приводила к потере связи между нодами.
2) Использование дополнительного witness (tie-breaker) сервиса, стоящего "сбоку", который отслеживает насколько жив tarantool master (например опрашивая все ноды java-сервис, видят ли они мастер ноду tarantool) и на основании получаемых статусов переключал все ноды java-сервиса на slave или запрещал им это делать. Логику работы при той или иной аварии тут нужно подбирать. Например: если большинство нод java-сервис видит что tarantool master жив, то принудительно (временно) выводить из эксплуатации ноды потерявшие связь с мастером, на давая им переключится на slave. Или в обратной ситуации, когда мастер видит меньшинство принудительно всех переключать на slave tarantool. В общем логика срабатывания дискуссионный вопрос.

Первый вариант вообще хорош, и кодить не нужно ) Вообще мы пока не поимели этой проблемы, а пока в разряде вероятных. Но меня беспокоит.
Второй вариант я обдумывал, но сервис «сбоку» точно также гипотетически может потерять только одну ноду, при том, что сами java-сервисы его будут нормально видеть. Как вариант, если мы примем допущение, что слэйв видит мастер, то он по факту начала приемов запросов на запись может послать запрос мастеру на прекращение работы. Однако здесь мы оказываемся в той же самой ситуации, что слэйв может потерять мастер. Мне кажется, что если ваш первый вариант дополнить грамотным размещением серверов с учетом топологии сети, то вероятность таких ошибок можно минимизировать. Но не исключить.

Идеала нет.
Со вторым вариантом важно что-бы и сами ноды знали, что есть witness и прежде чем куда-то переключатся нужно спросить у него, сам wintess может быть тоже распределенным сервисом с "авто-перевыборами" мастера при потере текущего. Логику работы нод в случае потери связи с каким либо компонентом, в том числе и с witness-сервисом, нужно тщательно продумывать. Сам witness не будет панацеей от всех проблем, но ряд возможных неприятностей позволит исключить. Ну и никто не мешает использовать оба варианта вместе, о чем я забыл упомянуть.

Обвязка вокруг всего этого получается большая и сложная, сопоставимая по сложности с самим сервисом. А хочется чего-то такого, чтобы раз — и заработало. Хотя бы того, чтобы затраты окупились, ибо потеря клиентских сессий на короткий промежуток времени раз в год экономически выгоднее поддержки сложной инфраструктуры. Сейчас сервис по доступности вполне укладывается в 99,99%.

Ну тут решать вам :). Я просто мыслями поделился.

Спасибо, есть на чем подумать.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий