company_banner

Надежный выбор лидера в Tarantool Cartridge



    Сегодня я немного расскажу о том, какие есть мысли по поводу фейловера в tarantool/cartridge. Сначала пару слов про то, что такое cartridge: это кусок lua-кода, который работает внутри tarantool и объединяет тарантулы друг с другом в один условный «кластер». Это происходит за счет двух вещей:

    • каждый тарантул знает сетевые адреса всех других тарантулов;
    • тарантулы регулярно «пингуют» друг друга через UDP, чтобы понять кто жив, а кто нет. Тут я намеренно немного упрощаю, алгоритм пинга сложнее чем просто request-response, но это для разбора не сильно принципиально. Если интересно — погуглите алгоритм SWIM.

    Внутри кластера все обычно разделяется на тарантулы «с состоянием» (master/replica) и «без состояния» (router). Тарантулы «с состоянием» ответственны за хранение данных, а тарантулы «без состояния» — за маршрутизацию запросов.

    Вот как это выглядит на картинке:



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

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

    Сначала поговорим о том, как узлы узнают адреса друг друга. Для этого у каждого из них на диске лежит yaml-файл с топологией кластера, то есть с информацией о сетевых адресах всех членов, и кто из них кем является (с состоянием или без). Плюс потенциально дополнительной настройки, но пока это тоже оставим в стороне. Конфигурационные файлы содержат настройки всего кластера целиком, и одинаковы для каждого тарантула. Если в них вносятся изменения — то вносятся синхронно для всех тарантулов.

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

    Сценарий — отказ узлов, переключение


    В ситуации когда отказывает роутер, все более или менее просто: клиенту достаточно пойти в любой другой активный роутер, и он доставит запрос до нужного стораджа. Но как быть, если упал, например, мастер одного из стораджей?

    Прямо сейчас у нас для такого случая реализован «наивный» алгоритм, который опирается на UDP ping. Если реплика в течение небольшого промежутка времени не «видит» откликов от мастера на ping, она считает, что мастер упал, и сама становится мастером, переключаясь в read-write режим из read-only. Роутеры действуют точно так же: если они не видят некоторое время отклика на ping от мастера, они переключают трафик на реплику.

    Это работает относительно неплохо в простых случаях, кроме ситуации «split brain», когда половина узлов оказывается отделено от другой какой-то сетевой проблемой:



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

    Сценарий — редактирование конфигурации при сбоях


    Еще один важный сценарий — это замена вышедшего из строя тарантула в кластере на новый, или добавление в кластер узлов, когда кто-то из реплик или роутеров недоступен.

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

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

    По этим причинам мы сейчас запрещаем редактировать конфигурацию через API, когда кто-то недоступен. Поправить ее можно только на диске, через текстовые файлы (вручную). Тут вы должны хорошо понимать, что вы делаете и быть очень внимательными: автоматика уже ничем не поможет.

    Это делает эксплуатацию неудобной, и это второй кейс, который нужно решить.

    Сценарий — стабильный фейловер


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

    Это может как быть, так и не быть проблемой. Мастер перед включением обратно «догонит» с реплики транзакционные логи, поэтому большого отставания по данным скорее всего не случится. Проблема будет только в том случае, когда есть неполадки в сети, и есть потеря пакетов: тогда скорее всего будет периодическое «мигание» мастера (flapping).

    Решение — «сильный» координатор (etcd/consul/tarantool)


    Для того чтобы избежать проблем со split brain, и дать возможность редактировать конфигурацию при частичной недоступности кластера, нам нужен сильный координатор, который устойчив к сегментации сети. Координатор должно быть можно распределить по 3-м датацентрам, чтобы при отказе любого из них сохранять работоспособность.

    Сейчас есть 2 популярных координатора, основанных на RAFT, которые для этого используют — etcd и consul. Когда в tarantool появится синхронная репликация, его тоже можно будет для этого использовать.



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

    Управление конфигурацией с сильным координатором


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

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

    Редактирование конфигурации тоже становится проще: это можно сделать через API любого тарантула. Он возьмет блокировку в координаторе, заменит нужные значения в конфигурации, дождется пока все узлы ее применят, и отпустит блокировку. Ну или в крайнем случае можно будет отредактировать конфигурацию в etcd вручную, и она применится ко всему кластеру.

    Редактировать конфигурацию можно будет даже если какие-то тарантулы недоступны. Главное, чтобы было доступно большинство узлов координатора.

    Фейловер с сильным координатором


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

    Алгоритм фейловера меняется вот как:

    1. Один из тарантулов в кластере выигрывает роль «главного» при помощи механизма блокировок в координаторе.
    2. Если главный тарантул видит через UDP-пинг, что кто-то из мастеров умер, он начинает процесс фейловера.
    3. Дальше он принимает решение о том, кто должен быть новым мастером.
    4. Пишет нового мастера в координатор.
    5. Все тарантулы в кластере получают уведомление об изменении конфигурации в координаторе и меняют свои роли соответственно, переходя в read-only или read-write.
    6. Если главный тарантул падает или оказывается отрезан по сети от других датацентров, он теряет роль главного, и через координатор проходят перевыборы.

    С координатором также возможна защита от flapping-а. В координаторе можно фиксировать всю историю переключений, и если в течение последних X минут было переключение мастера на реплику, то обратное переключение делается только явно админом.

    Еще один важный момент — это так называемый «Fencing». Тарантулы, которые оказываются отрезаны от других датацентров (либо подключены к координатору, потерявшему большинство), должны предполагать, что скорее всего оставшаяся часть кластера, к которой потерян доступ, имеет большинство. И значит в течение определенного времени все отрезанные от большинства узлы должны перейти в read-only. 

    Проблема с недоступностью координатора


    Пока мы обсуждали подходы к работе с координатором, мы получили просьбу сделать так, чтобы если координатор падает, но все тарантулы целые, не переводить весь кластер в read only.

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

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

    Планы на реализацию


    Сейчас мы собираем обратную связь и приступаем к реализации. Если вам есть что сказать — пишите в комментарии или в личку.

    План примерно вот такой:

    • Сделать поддержку etcd в tarantool [готово]
    • Фейловер с использованием etcd как координатора, с фиксацией состояния [готово]
    • Фейловер с использованием тарантула как координатора, с фиксацией состояния [готово]
    • Хранение конфигурации в etcd [в процессе]
    • Написание CLI-инструментов для ремонта кластера [в процессе]
    • Хранение конфигурации в тарантуле
    • Управление кластером при недоступности части кластера
    • Fencing
    • Защита от flapping–а
    • Фейловер с использованием consul как координатора
    • Хранение конфигурации в consul

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

    Благодарности


    Спасибо разработчикам из Почты Mail.ru и админам за предоставленный фидбэк, критику и тестирование.
    Mail.ru Group
    Строим Интернет

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

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое