Pull to refresh

Comments 25

В чем коммерческая выгода (стартап-же) от новой СУБД, да еще как надстройка на KV-базе (допустим Redis) ?
Какие проблемы решает ваша новая СУБД?

Выгода в уменьшении на порядок бюджетов на разработку ну и в разы на сопровождение. Наши рестораны мы бы запустили за пару месяцев на hetzner с нуля, ну а так несколько человеко-лет ушло бы (как у извеcтных мне коллег на Azure). Сейчас, конечно, уйдет несколько больше - ввиду глобальности целей.

Касательно Redis - нет, пока не поддерживаем даже в планах, только Cassandra/Scylla/FoundationDB/bbolt. Поправил в статье.

Кластер будет ставиться "прозрачно" для пользователя, просто даете IP-адреса, и все. В случае выхода из строя узла нужен IP адрес нового узла, произойдет горячая замена, без простоев.

От разработчиков будет требоваться уметь в командную строку Linux и проектировать БД на уровне схем. Знание Cassandra и проч. приветствуется, но не требуется.

Таков план. Реальность, возможно, внесет некоторые коррективы, но пока все в допустимых рамках.

Как страшно и трудно жить!

Спасибо, статья замечательная!

Прочитал, осознал, ушел плакать...

Нельзя читать то, что кто-то одновременно пишет, независимо от успешности пишущей транзакции.

А давайте попробуем определить, что значит «нельзя»? Ну вот как бы чтение результатов транзакций, которые еще не сделали commit, его ведь разрешали не просто так, а ради решения каких-то задач. Которые видимо допускают, что результат задачи не будет консистентным. Или самым свежим. Ну так, условно — если нам нужно реплицировать данные в другую БД, нас больше устраивают данные, пусть отстающие по времени (с известным отставанием), но зато гарантированно полученные к определенному моменту.

А давайте попробуем определить, что значит «нельзя»?

Давайте попробуем. Если уровень изоляции исключает P1, в формулировке "критиков", то движок БД не должен допускать вот таких историй: w1[x]...r2[x]...(c1 or a1)

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

А почему сразу ошибка? Например это могут быть статистические данные. Если из миллиона записей в итоге пара откатиться, то это все будет в пределах погрешности и по бизнесу может быть допустимо.

Не все сценарии работы с данными требуют жёсткой консистентности.

>А почему сразу ошибка?
А какая разница? Я лишь про то, что одна транзакция уже прочитала данные, которые потом (вдруг) оказались не консистентными, потому что другая транзакция (позже) откатилась. То есть мы тут имеем дело с асинхронной коммуникацией. Которая всегда сложнее синхронной, и вообще не всегда возможна — потому что клиент тупо уже отрубился недоступен.

А где в этой картине мира находятся Local-First СУБД? Я вижу так:

  • Они Snapshot Isolation, так как каждый процесс исполняет свои операции последовательно над локальной копией базы.

  • Они Total Available так как для работы связь с серверами и другими клиентами не обязательна. Аутентификация и авторизация обеспечивается криптографией.

  • Они Causal Consistency, так как следствия никогда не обгоняют причины.

  • Они Strong Eventual Consistency, так как после синхронизации приходят к единому состоянию.

При этом возможны лишь следующие аномалии:

  • Write Skew, так как причинность не отслеживается, а явного конфликта изменений нет. Хотя, если всё же отслеживать причинность, то можно и от этой аномалии избавиться.

Ничего не упустил?

Тут надо на архитектуру смотреть. Мы сейчас "пилим" вот такое:

База распределенная (две копии), репликация асимметрична и асинхронна.

Snapshot Isolation

На клонированной из облака копии Strong Partition Serializable для пишущих транзакций, Eventual Consistency для транзакций на чтение.

Total Available

В нашем случае нет (хотя, видимо, зависит от определений), в "облако" писать нельзя пока активен Local Box (aka Edge Node)

Causal Consistency, Strong Eventual Consistency

Пожалуй, но, в нашем случае, только с применением оргмер. Без них, например, можно получить split brain - в облаке отметить что Local Box "умер", соответственно, с облачной копией теперь можно работать, но и с Local Box технически можно продолжать работать, и тогда, конечно, настанет время удивительных чудес с перемещениями во времени.

У нас попроще архитектура:

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

Strict Serializable предполагает, что на всех узлах результаты транзакций будут появляться в одном и том же прядке, что не обеспечить при работе только с локальной базой. Так что SPS тут совсем не выходит. А вот Total Available как раз получается, так как можно писать в базу даже в оффлайне, а при синхронизации, через CvRDT все изменения конвергируют. Так что временный Split Brain совсем не страшен.

А вот Total Available как раз получается, так как можно писать в базу даже в оффлайне

Согласно jepsen.io Cursor Stability и выше а также Snapshot Isolation и выше не могут быть Total Available.

Подозреваю, имеет место разница в формулировках либо какие-то особенности работы с данными, типа каждый пир только вставляет данные.

Это потому, что там рассматриваются только Cloud-First субд, где клиент может сначала к одному узлу подключиться, а потом к другому и получить разные результаты. В случае Local-First можно спокойно коннектиться к любым узлам, даже если у них Split-Brain, тогда сервера синхронизируются не напрямую, а опосредованно, через клиента.

У Вас все-таки такая архитектура:

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

Это случай "Clients only talk to the same servers, instead of switching to new ones". В таком сценарии обеспечиваются уровни изоляции и согласованности, обозначенные синим и желтым цветами.

Конкретно с определением Snapshot дело обстоит так - можно обеспечить все требования кроме First-committer-wins. Это требование, в случае использования CRDTs, является излишним (так как нацелено на Lost Update, каковой невозможен с такими типами) тем не менее, оно есть в приводимых формулировках.

Можно как-то по другому назвать, например, Snapshot-CRDTs.

Это случай "Clients only talk to the same servers, instead of switching to new ones"

Не совсем. Клиент может спокойно менять сервер. То есть это голубой цвет. Но при этом обеспечивается Causal Consistency - всё, что ты видел на одном сервере, ты увидишь и на любом другом + что-то свежее.

Интересно, как при свободной смене сервера обеспечить Read-Your-Writes? Пишем в x=x+1 (=9+1=10 ) в SRV1, репликация асиннхронная(?), после записи SRV1 выпадает из сети, репликация не завершена. Идем на SRV2 и там читаем x==9.

Как избежать такой ситуации?

Это возможно только в Local-First субд, где сам клиент неявно выступает в качестве посредника в синхронизации серверов. То есть, когда он подключается к SRV2, то передаёт ему и это изменение и любое другое, которое SRV2 ещё не видел.

У клиента для этого еще одна база должна быть и именно в нее он и должен всегда писать First.

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

Ну т.е. клиент всегда пишет в одну базу, "Clients only talk to the same servers, instead of switching to new ones".

Как только он переключится возможна потеря уровня Read-Your-Writes.

Клиент пишет в одну базу, но общается с любыми серверами. Локальная база одна и не "переключается".

Strong Eventual Consistency: в одной «локальной копии» я купил Бентли, в другой - Ламборгини. Денег было на одну машину. Как это будет синхронизироваться?

«Овердрафт» - видимо так?

  1. Очень крутое введение в проблематику

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

Я лично удивлён отсутствием ссылки на CAP-теорему

Это следующий этап, КМК. Сначала определяем понятие Consistency, а затем уже можно его связывать с другими, например с Availability и Partition tolerance.

Sign up to leave a comment.

Articles