Pull to refresh
34
0
Сергей Петренко @sergepetrenko

Пользователь

Send message

К цене ещё можно добавить сильно увеличенный объём паразитного внутреннего трафика из-за постоянных броадкастов для кворума.

Верно.

На самом деле линеаризуемость легко обеспечить и без всяких кворумов, если разместить реплику на каждом клиенте. Тогда даже если один сервер упадёт и клиент подключится к другому, то не увидит отката истории. Я уж не говорю про возможность коммитить в такой мультимастер синхронно даже находясь в оффайне.

А вот эту мысль не понял. Можете объяснить? Разве это не про causal consistency?

В журнал мастер пишет транзакции сразу по получению. Это не значит что она уже "применилась". "Применять" транзакцию нужно только после того как получено подтверждение от >1/2 кластера что они тоже записали это в свои журналы (commit_index нужен именного для этого).

Да, именно так работает рафт. Потому что в нём есть только "синхронные" транзакции.

В Тарантуле есть и "асихнронные" и "синхронные". И первые - это не просто асинхронный интерфейс для вторых. Это другой тип транзакций с другим поведением. Как я уже написал, асинхронные применяются сразу после попадания в журнал мастера. И в этот же момент отвечают клиенту.

У нас тип репликации для транзакции выбирает пользователь. Выбрал "синхронную" - получает рафт. Выбрал "асинхронную" - получает что-то среднее со своими проблемами, не такими, как в рафте. Я про эти проблемы и пишу в статье.

До этого - клиенту нельзя давать ответ об успешной записи, это не даёт вообще никаких гарантий. Кроме отката транзакций raft-ом ещё есть ситуации аварийного отключения сервера и если вы не делаете flush после каждой записи (что убивает производительность) - клиент так же успешно потеряет транзакцию.

Да, и как правило пользователь знает об этом риске. Есть ведь системы, которые ни рафт, ни кворумную ("синхронную") запись не поддерживают. Про них нельзя сказать, что они не дают никаких гарантий. Зато они позволяют писать с низкой latency. Потому что не надо ждать, пока запись доедет до большей части узлов.

Но процесс опроса не мгновенный, так что к моменту отсылки (и тем более приёма) ответа, данные могут быть уже не актуальны. Так что кворум на чтение принципиально не гарантирует актуальности.

Да, кворум на чтение гарантирует только то, что ответ будет актуален на момент получения запроса, но не на момент отправки ответа.

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

Наверное, мы с вами разное понимаем под "асинхронной транзакцией". Мы возвращаем клиенту ответ только после того, как транзакция записана в журнал мастера. В этот момент она уже применилась, и клиент вполне может на это полагаться. Никакого подтверждения лучше он не получит. Только то, что транзакция есть в журнале одного узла. А "асинхронная" она потому что мы не дожидаемся её попадания в журналы реплик прежде чем ответить клиенту.

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

PS. Ну и выводы ИМХО не верные, рафт обрабатывает все эти случаи абсолютно корректно, вы пытаетесь сделать из него то чем он не является и ловите проблемы.

Это правда. При "ручном понижении", двух нодах или асинхронных транзакциях это уже не рафт. Но все эти компромиссы могут быть полезны в конкретных случаях. Другое дело, что гарантии при этом явно снижаются. Мы лишь пытаемся сделать так, чтобы пользователь получил какой-то повышенный уровень консистентности по сравнению с полным отказом от рафта. Ну и, конечно, от пользователя зависит, пользоваться этими трюками, или нет. Если не пользоваться, то получите полноценный рафт со всеми его гарантиями.

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

PreVote действительно отрабатывает перед голосованием, и можно представить такой набор "миганий", что большинство перестанет видеть лидера, кто-то из большинства проведёт проверку Pre-Vote и начнёт голосование. От этого ни оригинальный Raft, ни Pre-Vote не защищают. Можно election_timeout менять разве что. Чем больше таймаут, тем более долгие мигания можно пережить без смены лидера. Но и время реакции на настоящий отказ лидера увеличивается.

по причине потери связи одним из участников я в реализации рафта для Ergo Framework ввел понятие кворума. https://github.com/ergo-services/ergo/blob/master/gen/raft.go

Насколько я понимаю, у вас в кластере есть подгруппа узлов, которые могут голосовать, а остальные - learners? А что происходит, когда кто-то из кворума отказывает или с ним теряется связь? Находят нового члена кворума?

Почему же, большинство в кластере из 3 узлов - 2, A и B в примерах связаны. "Большинство" имеется в виду, считая себя самого, то есть A связан с самим собой и с B, и этого достаточно.

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

Спасибо, документацию дополним.

Я считал wal_mode отвечает только за запись на диск. А если хочется
отключить репликацию необходимо создавать space с параметром is_local = true

Вы говорите всё правильно. Видимо, я недостаточно ясно выразился в статье. Если мастер не ведёт журнал (wal_mode = 'none'), реплики к нему подключаться не смогут, и при попытке подключиться к такому мастеру будут получать ошибку:

ER_UNSUPPORTED: Replication does not support wal_mode = 'none'

Почему это так, я рассказал в статье. Мастеру неоткуда брать поток данных для реплики.

Зато можно сделать наоборот: к мастеру с работающим журналом подключить реплику с wal_mode = none. Так репликация работать будет.

Спасибо!

Насчёт повышения кворума: при любом значении, большем или равном N/2 + 1, выполняются все гарантии, которые я озвучил в статье. То есть, в каждых выборах либо не побеждает никто, либо номинируется единственный лидер, причём у этого лидера точно есть все транзакции, которые подтвердил предыдущий лидер.

При этом, чем ближе кворум к N, тем выше шансы потерять доступность кластера на запись: если кворум N/2 + 1, кворум будет собираться при потере почти половины реплик; если же кворум N, то отказ любой из реплик приведёт к тому, что транзакции не смогут собирать кворум, и в выборах не сможет победить никто.

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

Я всё же считаю, что оптимальное значение — N/2 + 1. Его достаточно для того, чтобы выполнялись все гарантии про единственность лидера и наличие на нём всех подтверждённых данных, и при этом такой кворум не накладывает слишком строгих ограничений на доступность реплик
Спасибо за комментарий!
Я не совсем точно выразился в статье. Сейчас попробую объяснить более подробно.
Те транзакции старого лидера, которые есть на новом лидере, он разошлёт остальным, а затем подтвердит.
Всё, чего нет на лидере, но может быть на каких-то из слейвов, лидер попросит отменить. Ничего криминального в этом нет. Раз за лидера проголосовало большинство слейвов, значит у него есть все подтверждённые транзакции, и попросит отменить он как раз такие «потеряшки».

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Registered
Activity