Pull to refresh

Comments 6

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

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

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

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

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

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

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

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

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

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

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

И асинхронные интерфейсы обычно делают так что им можно предоставить колбек который потом асинхронно вернет результат. А не "ну потерялось подумаешь".

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

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

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

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

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

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

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

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

наилучшая с точки зрения доступности пара кворумов — W = N / 2 + 1, R = N / 2 + 1 — позволяет пережить отказ (N - 1) / 2 узлов без нарушения консистентности

Но эта схема при этом максимизирует нагрузку на сеть. Например, для 11 узлов, на каждый запрос от клиента (что на запись, что на чтение) происходит пересылка минимум 20 сообщений между узлами. В то время как чтение без кворума может ограничиться лишь 2 сообщениями, чтобы проверить свою актуальность у лидера. То есть разница на порядок.

Чтобы эти операции приводили к консистентной картине, они должны выполняться над самой свежей версией данных.

Либо надо использовать конвергентные структуры, операции над которыми можно переставлять местами.

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

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

Sign up to leave a comment.