Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 07.07.18 17:54
Оценка: 6 (1)
Всем привет.
Вот есть система, которой присущ сабж. Для конкретного примера — который меня вдобавок в первую очередь интересует — возьмем Elasticsearch.
Есть по меньшей мере три наиболее неприятных ситуации, которые могут возникать.
1) Пользователь выполняет создание некой сущности в каком-то веб-приложении, потом запрашивает список этих сущностей — но не видит в нем созданную, потому что приложение ищет через elasticsearch, и (как одна из причин) попадает на тот шард, который еще не успел получить реплику сущности. Как после этого пользователю открывать созданный документ — с ходу непонятно (хотя если дать кнопку "обновить" то вероятно постепенно привыкнет, но выглядит это как-то некрасиво).
2) Аналогично п.1, но еще подлее. Пользователь то видит в списке созданную сущность, то не видит — вплоть до того что например он открывает редактор созданной сущности, вносит изменения туда, а при попытке сохранить получает ошибку из-за того, что сущности якобы нет (потому что опять сходил не на тот шард). Конечно не все приложения при сохранения изменений пойдут в эластик искать там сущность (все-таки мало кто эластик использует как первичную БД), но если вместо эластика например Кассандра — вполне возможно; или могут упасть если они пытаются делать при сохранении UPDATE эластика, а он ведь вроде падает если документа с таким id не нашлось.
3) Код клиента вызывает после создания или сохранения сущности ее повторное чтение (ну например в форме редактирования кнопка "Сохранить" по замыслу не должна закрывать эту форму). И соответственно повторное чтение не может найти сущность или находит ее вариант до изменений. Ну хотя бы для этого сценария есть решение достаточно очевидное — структурировать код клиента так, чтобы не запрашивать данные заново с бека, а использовать те, которые мы отправляли на сохранение.

Так вот, как вы с этим в своих проектах справляетесь?
Ну я знаю что кто-то никак не заморачивается, дескать ну получит юзер ошибку — ну и ладно, значит бог его все равно не любит; а если не увидит документ то дадим ему кнопку Обновить. По 1-ой проблеме еще наверно можно как-то по websocket подписываться на апдейты и подтягивать автоматически, чтобы не заставлять обновлять самостоятельно; еще я слышал о людях которые добавляли к получаемому от бека списку фиктивные строки для только что созданных документов, но при запросах по одной странице — если пагинация используется — это будет конфликтовать с сортировкой, которая по идее проводится на бэке, ведь неясно на какую страницу должна попасть эта фиктивная строка.
Еще я читал про read own writes консистентность и про monotonic read консистентность, они бы позволили решить эти проблемы (монотонность решила бы хотя бы 2-ую). Но как их подружить с системой, которая изначально их сама не поддерживает (тот же эластик например), я не представляю. Вот например для read-own-writes в одной статье предлагали PouchDB применять как локальное хранилище для копии вносимых изменений, но если есть такой кэш, какие должны быть правила eviction для него? До каких пор держать в нем наши изменения? И что если сессии пользователя — не sticky, и следующий запрос его может прийти на другой инстанс приложения — уже в другой pouchdb? Или даже если они sticky например, но использовавшийся в последний раз инстанс — отвалился? Тут по идее надо распределенный кэш тогда вместо pouchdb — но опять возникают вопросы, ведь такой кэш тоже должен быть AP системой (как и сам эластик ну или там кассандра) и потому при переключении клиента на другую ноду может оказаться, что там в этот момент еще не самое свежее состояние сессии. Бида короче =) А, ну еще наверно можно было бы на стороне клиента держать кэш вместо этого, но там опять непонятно как настроить eviction так, чтоб кэш не разрастался безгранично.
Как прикрутить к эластику monotonic read consistency, если у него нет глобального понятия "версия всех данных", я тоже не понимаю.

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

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Отредактировано 07.07.2018 18:27 Slicer [Mirkwood] . Предыдущая версия . Еще …
Отредактировано 07.07.2018 18:19 Slicer [Mirkwood] . Предыдущая версия .
Re: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 07.07.18 18:05
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>2) Аналогично п.1, но еще подлее. Пользователь то видит в списке созданную сущность, то не видит — вплоть до того что например он открывает редактор созданной сущности, вносит изменения туда, а при попытке сохранить получает ошибку из-за того, что сущности якобы нет (потому что опять сходил не на тот шард).


Тут наверно можно в некоторых системах управлять affinity между идентификатором сессии/логином юзера и номером инстанса эластика (ну или вообще БД) который хранит primary shard. То есть запросы указанного id от указанного пользователя будут всегда ходить на один и тот же шард. Может и так кто-то делает? С другой стороны это во-первых ставит под удар балансировку нагрузки, а во-вторых опять-таки шард же может и отвалиться и тогда вероятность не увидеть свои изменения опять появляется (ну или может банально не успеть обновиться, если он не входит в кворум по репликации).

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Eventual consistency
От: takTak  
Дата: 07.07.18 18:24
Оценка:
вспомни, когда ты в последний раз по интернету билеты на самолёт покупал: что ты там в окошке видел, когда нажимал в последний раз на кнопку "купить" ? скорее всего , что-то типа "мы приняли Ваш заказ, Вы получите скоро от нас подтверждение"

как ты у себя это же сделаешь —
1)то ли так же, а потом, когда сущность везде отреплицируется, и ты веб сокетами обновишь список
2) либо сразу же обновишь список на клиенте, не дожидаясь ответа от сервера
это, в принципе — твоё личное дело
Re[2]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 07.07.18 18:35
Оценка:
Здравствуйте, takTak, Вы писали:

T>вспомни, когда ты в последний раз по интернету билеты на самолёт покупал: что ты там в окошке видел, когда нажимал в последний раз на кнопку "купить" ? скорее всего , что-то типа "мы приняли Ваш заказ, Вы получите скоро от нас подтверждение"

Это безусловно выход. Для систем, в которых действие можно логичным образом представить пользователю как многоэтапное: есть заказ и есть результат его выполнения, есть исходные данные (форма ввода) и результат (билет). И то могут возникать непонятки: "вы же написали что приняли заказ, почему я не вижу его в списке заказов в личном кабинете?"
Но если например пользователь создает заявку, которая должна в какой-то системе учета заявок появиться (да те же трекеры типы jira/redmine), то интуитивно процесс создания заявки вообще не многоэтапный: в сознании пользователя сама заявка и является результатом ее создания. Тут разве что дурить голову юзеру сообщениями вроде "заявка проходит премодерацию (на самом деле нет — но такому ограниченному типу как ты это не объяснишь) и скоро появится на сайте", наверно.

А обновить список на клиенте сразу — это ведь тоже не так просто. Как предлагаешь к этому подойти? Вот мне нужна 10-ая страница списка документов с сервера — потому что сейчас мы ее просматриваем — как мне понять на клиенте, попадет в нее добавленный только что документ или нет? А постраничный просмотр сейчас по моему опыту есть почти везде, особенно если объемы данных или нагрузка таковы, что есть смысл использовать масштабируемые и highly available решения.

Websocket тоже решение ненадежное. Кто именно должен сделать вывод что изменения полностью залиты? Нет такого диспетчера который бы твердо знал что на всех шардах лежат нужные данные. То есть если например бэкэнд будет пинговать эластик и когда ему удастся там увидеть данные то он пошлет по websocket уведомление, то всегда может быть что на каком-то другом шарде этих данных все еще нет; и если клиент, получив уведомление, сделает рефреш и попадет на тот шард где данных нет, то в списке их опять не будет =)

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Отредактировано 07.07.2018 18:51 Slicer [Mirkwood] . Предыдущая версия . Еще …
Отредактировано 07.07.2018 18:40 Slicer [Mirkwood] . Предыдущая версия .
Re[3]: Eventual consistency
От: takTak  
Дата: 07.07.18 18:46
Оценка: 10 (2)
если у тебя SPA, то там сам можешь симулировать на клиенте, что всё уже произошло, что усложняет клиента, конечно (в случае ошибки , однако, надо будет таки сказать: "оопс, произошла ошибка и т.д. и убрать данные с клиента")

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

твоя первая попытка решения: использовать sticky session теоретически может прокатить, но как ты сам уже заметил, в чём тогда смысл использовать elastic search, если тоже самое ты сможешь обеспечить обычным веб приложением
Re[4]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 07.07.18 19:06
Оценка:
Здравствуйте, takTak, Вы писали:

T>если у тебя SPA, то там сам можешь симулировать на клиенте, что всё уже произошло, что усложняет клиента, конечно (в случае ошибки , однако, надо будет таки сказать: "оопс, произошла ошибка и т.д. и убрать данные с клиента")


Ну я пытался объяснить, в чем проблема с симуляцией. Как минимум в определении того, где добавленное располагается относительно всего остального. Другие-то вещи (прямой доступ по id, или даже поиск по каким-то критериям) в большей или меньшей степени можно подделать.
Хотя вообще-то да, я ранее написал неверно: зная критерий сортировки, можно, уже получив N-ную страницу с сервера, понять, должен ли внутрь нее попадать новый документ. Может и вариант. Но опять-таки, вот мы прочитали список с сервера, наш документ должен идти третьим на этой странице, а его нет. Это может означать что наш документ еще не попал на этот шард. Но это с тем же успехом может означать что его кто-то уже успел удалить =) И в этом случае ясное дело не нужно вставлять в список нашу копию. Проблема.

И еще, кстати, вставка внутрь принятого от сервера списка означает, что нужно из него тогда последнюю или первую строку выкинуть; а так как выкинутая появляется только на этой странице и никаких других, то получается юзер никогда ее не увидит, как бы он ни переключал страницы, до тех пор пока наша фиктивная запись не придет ему честно с сервера. Хотя тут тоже можно побороться — запрашивать с сервера сразу по 2 страницы вместо одной, и вырезать из них нужный кусок в зависимости от того где находится фиктивная запись относительно полученных. Так что это вроде бы решаемо.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Отредактировано 07.07.2018 19:08 Slicer [Mirkwood] . Предыдущая версия .
Re[5]: Eventual consistency
От: takTak  
Дата: 07.07.18 19:23
Оценка:
чего-то ты намудрил имхо

короче, если у вас там SPA, то ты симулируешь на клиенте, что вставка была успешной: это видно только на том клиенте, откуда была произведена вставка, это было во-первых

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

хотя, конечно, такого хитрого клиента написать нетривиально
Re: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 09.07.18 11:13
Оценка:
Я на всякий случай еще раз обозначу, почему предложение takTak не получается реализовать.
Вот мне попалась статейка https://10consulting.com/2017/10/06/dealing-with-eventual-consistency/ — там описаны такие подходы как имитация, блокировка на стороне клиента через поллинг, блокировка на стороне сервера и подписка на окончание действия.
И это прекрасно работает, когда система не сразу обновляет состояние в ответ на запросы клиента, но хотя бы консистентна по читаемым данным (в смысле, любые запросы к одним и тем же данным, пока эти данные никто не изменил, дают один и тот же ответ). У них в статье "неконсистентность" имеется между разными данными в одной БД, а у меня проблема более общая — та которая в CAP-теореме — нестыковка между ответами разных узлов при чтении одних и тех же данных.
И вот из-за нее все эти подходы обламываются. К примеру, клиент делает поллинг сервера и находит что добавляемые данные прочитались. Он довольный продолжает работу, снова запрашивает эти данные — но теперь запрос попадает на другой шард, там этих данных пока еще нет и получается что рано было радоваться.

Come on, ну наверняка же тут на форуме люди должны быть в курсе проблемы =)

Slicer

P.S. Фальшивый объект мог бы сработать — если мы решим его вообще не обновлять автоматически, а так и держать на клиенте до тех пор, пока клиент не решит перечитать данные заново. Ну а если и правда решит? Например начнет в фильтр для поиска вбивать какие-то значения. Да, в 99% случаев к этому моменту нужные ему данные уже везде зальются. Но могут и не успеть =)
P.P.S. Да, если бы у нас была классическая реляционка и притом мы бы не приделывали специально на UI асинхронность, то "могут и не успеть" означало бы что после нажатия на "Сохранить" (условно говоря) юзер бы тупо ждал несколько секунд пока данные прольются везде. Ну значит и ждал бы изредка, зато бы у него потом вопросов не возникало "а где?"
P.P.P.S. Или никто и не пытается спрятать неконстистентность в 100% случаев и довольствуется 99.9%? А если пару раз в день какие-то пользователи заметят что-то не то и удивятся — бог с ними? (Но опять же одно дело "я не могу найти мой документ... а, во, теперь он есть", а другое "твою мать вся моя корзина покупок пропала" после переключения на другой шард, или "почему я открыл документ а теперь при редактировании пишет что его нет?")
Специалист — это варвар, невежество которого не всесторонне :)
Отредактировано 09.07.2018 11:29 Slicer [Mirkwood] . Предыдущая версия . Еще …
Отредактировано 09.07.2018 11:26 Slicer [Mirkwood] . Предыдущая версия .
Отредактировано 09.07.2018 11:20 Slicer [Mirkwood] . Предыдущая версия .
Re[2]: Eventual consistency
От: takTak  
Дата: 09.07.18 18:23
Оценка: 4 (1)
SM>имеется между разными данными в одной БД, а у меня проблема более общая — та которая в CAP-теореме — нестыковка между ответами разных узлов при чтении одних и тех же данных.
SM>И вот из-за нее все эти подходы обламываются. К примеру, клиент делает поллинг сервера и находит что добавляемые данные прочитались. Он довольный продолжает работу, снова запрашивает эти данные — но теперь запрос попадает на другой шард, там этих данных пока еще нет и получается что рано было радоваться.


ничего не понимаю...

как не работает? всё работает: следи за пальцами:
клиент делает запись А с Id = "c6e45efb-2908-45a3-bfa9-a58f6b9822fb", асинхронно команда на создание записи А попадает на какой-то сервер, на этом сервере сидит command handler, который сохраняет запись А в агрегате (Entry in EventStore) , в котором по факту сохранения происходит raise entryCreatedEvent/ message.Send(entryCreatedMessage) , все твои дб-сервера подписаны на это событие и обрабатывают асинхронно создание записи А и по прошествии обработки в свою очередь делают entryHasBeenSavedEvent, причём где-то там у тебя находится event / message handler, который считает для каждой записи A с Id = "c6e45efb-2908-45a3-bfa9-a58f6b9822fb" до трёх или пяти entryHasBeenSavedEvent's или сколько у тебя там разных инстанций базы, и после того, как это число достигнуто, обновляет список твоего изначального или всех клиентов через веб сокет

клиент, который создал запись А, должен симулировать существование записи А до тех пор, пока он не получит через веб сокет либо подтверждения либо опровержения (тогда пользователю нужно чего-то показывать)

все остальные клиенты могут увидеть запись А только после того, как она будет сохранена в той базе, к которой они непосредственно обращаются

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

отказоустойчивой всё делается политикой повторения событий/ сообщения: если какой-то comannd / event handler не смог сохранить запись в своей базе, он из своей собственной очереди снова получит то же самое сообщение, которое он не смог обработать 5 или 105 раз в зависимости от конфигурации
Отредактировано 09.07.2018 18:29 takTak . Предыдущая версия . Еще …
Отредактировано 09.07.2018 18:25 takTak . Предыдущая версия .
Отредактировано 09.07.2018 18:23 takTak . Предыдущая версия .
Re[3]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 09.07.18 19:00
Оценка:
Здравствуйте, takTak, Вы писали:

T>дб-сервера подписаны на это событие и обрабатывают асинхронно создание записи А и по прошествии обработки в свою очередь делают entryHasBeenSavedEvent, причём где-то там у тебя находится event / message handler, который считает для каждой записи A с Id = "c6e45efb-2908-45a3-bfa9-a58f6b9822fb" до трёх или пяти entryHasBeenSavedEvent's или сколько у тебя там разных инстанций базы

А, так ты хотел именно от всех шардов зеленый свет получить! Импровизированный countdown latch Я думал, что такое тоже не получится (может ли эластик генерировать в каком-то виде событие об окончании индексации, я совсем не уверен). Впрочем, ведь в эластике есть кажется готовый инструмент, по крайней мере раньше был — можно указать, что запись завершается только после репликации на N узлов вместо обычного кворума. Получается такая же схема как у тебя, прямо из коробки.
Ок, будь это не эластик, это даже могло бы сработать. Но с эластиком есть дополнительная засада, насколько я понимаю, эластик не сразу после окончания индексации способен найти записанные изменения: сегменты рефрешатся с некой задержкой, по умолчанию вроде не более до 1 секунды. Конечно можно вставить задержку в 1 сек, но ведь реально 1 сек может превратиться и в несколько большее время (скажем сервер сильно загрузили), заранее неизвестное. С учетом этого есть какие-то идеи?

T>все остальные клиенты могут увидеть запись А только после того, как она будет сохранена в той базе, к которой они непосредственно обращаются

Та же самая проблема: они могут обращаться то к одному шарду, то к другому — куда их пошлет балансировщик кластера БД. Поэтому они могут то видеть эту запись, то не видеть. Что тоже в общем-то фигово. Несколько лучше чем видеть/не видеть свои собственные изменения, но если надо чужой документ подредактировать то тоже не айс.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[4]: Eventual consistency
От: takTak  
Дата: 09.07.18 19:11
Оценка:
SM>все остальные клиенты могут увидеть запись А только после того, как она будет сохранена в той базе, к которой они непосредственно обращаются
SM>Та же самая проблема: они могут обращаться то к одному шарду, то к другому — куда их пошлет балансировщик кластера БД. Поэтому они могут то видеть эту запись, то не видеть. Что тоже в общем-то фигово. Несколько лучше чем видеть/не видеть свои собственные изменения, но если надо чужой документ подредактировать то тоже не айс.


я не в курсе, как elasticSearch работает, я тебе о классическом CQRS рассказывал: там всё отправлением сообщений в очереди решается

такой вариант, когда в одном узле запись есть, а через секунду в другом узле ещё нет, при CQRS практически невозможна, CQRS как раз и занимаются, чтобы скорость прохождения сообщений максимально увеличить

если все твои узлы / базы подписаны на сообщение и параллельно одно и то же сообщение начинают обрабатывать, то почему через секунду оно не должно быть быть обработано на другом узле? транзакций (блокировок) ты не используешь, скалировать по горизонтале можешь до бесконечности, почему обработка должна длиться дольше сотни миллисекунд?
Re[5]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 10.07.18 02:18
Оценка:
Здравствуйте, takTak, Вы писали:

T>если все твои узлы / базы подписаны на сообщение и параллельно одно и то же сообщение начинают обрабатывать, то почему через секунду оно не должно быть быть обработано на другом узле? транзакций (блокировок) ты не используешь, скалировать по горизонтале можешь до бесконечности, почему обработка должна длиться дольше сотни миллисекунд?

Ну мало ли. Холодный старт одного из узлов. Кэши подвели. Узел почему-то перегружен. Канал между какими-то двумя узлами перегружен или "мерцает". Ну или любое временное разделение узлов по каким-то причинам (то самое, которое P из CAP) — но это уже экстрим, там возможно ждать с фейком придется довольно долго, если мы хотим подтверждение от всех узлов.
Понятно что в плановом режиме работы всех этих проблем просто не будет, это ну допустим 1% всех запросов.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[5]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 10.07.18 05:44
Оценка:
Здравствуйте, takTak, Вы писали:
T>я не в курсе, как elasticSearch работает, я тебе о классическом CQRS рассказывал: там всё отправлением сообщений в очереди решается

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

Далее, поскольку от Эластика не выйдет получить сообщение об успешном рефреше сегментов, то подход с фейком не сработает (ну или надо ставить дополнительную задержку еще на 1 секунду и молиться). Какие-то другие рабочие подходы есть? Которые не полагаются на ожидание таких сообщений. Например вроде должен работать подход с монотонностью, но он кажется опять требует специальной поддержки в используемой БД? Или можно все же привязать сессию пользователя к конкретному шарду БД (если это поддерживается), а в случае выхода шарда из строя, так и быть, рисковать появлением "мерцания" на какое-то время (да, это опять неполное решение, но если подумать, любое решение с fault tolerance и shared session не даст полной защиты от потери последних данных, если только это не будет некое CP решение — а тогда оно отправит псу под хвост availability и всей системы в целом). Опыта совершенно нет в этом, не представляю, какой путь лучше/общепринятый. А ведь проектов с тем же эластиком пруд пруди (хоть на джаве, хоть на вот этом вот MEAN стеке).

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[6]: Eventual consistency
От: takTak  
Дата: 10.07.18 06:26
Оценка:
я сам с этом не работал, но у майкрософта не так давно в их Service Fabric появились reliable dictionary and reliable queue classes, это типа загруженные в память коллекции , с которыми непосредственно работа происходит, как потом эти штуки сохраняются — дело десятое, важно что все узлы работают с ними, по сути это распределённый кэш в памяти, т.е. специально создан дополнительный слой, который решает проблемы о которых ты говоришь

если опыта с CQRS нет, то я бы не рекомендовал туда сразу бросаться, ты можешь на досуге сам потренироваться на кошечках, погугли , попробуй найти готовые примеры https://technology.amis.nl/2018/05/22/simple-cqrs-tweets-to-apache-kafka-to-elastic-search-index-using-a-little-node-code/

обычно вкупе с CQRS нужно выстраивать свою архитектуру по мониторингу сообщений, чтобы отслеживать застрявшие где-то сообщения, это тоже довольно нетривиально
Отредактировано 10.07.2018 6:30 takTak . Предыдущая версия .
Re: Eventual consistency
От: Cyberax Марс  
Дата: 10.07.18 08:44
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>1) Пользователь выполняет создание некой сущности в каком-то веб-приложении, потом запрашивает список этих сущностей — но не видит в нем созданную, потому что приложение ищет через elasticsearch, и (как одна из причин) попадает на тот шард, который еще не успел получить реплику сущности.

Я не очень понимаю зачем такое вообще нужно. Почему нельзя использовать обычную БД, если требуется read-after-write целостность?
Sapienti sat!
Re[2]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 11.07.18 05:43
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Я не очень понимаю зачем такое вообще нужно. Почему нельзя использовать обычную БД, если требуется read-after-write целостность?

Разумный вопрос. Но он распадается на два, постараюсь кратко ответить.

* Если "обычные" это полностью консистентные, то я отвечу так. Хотелось научиться применять eventual consistency решения, потому что в будущем, чувствуется, мне все чаще будут встречаться задачи такого рода, где масштабируемости или отказоустойчивости или производительности или возможностей (взять тот же эффективный поиск подстрок, например) классических СУБД будет не хватать, особенно с учетом пожеланий заказчиков по бюджету. А еще хотелось научиться конкретно эластик применять — пусть даже в сочетании с классической БД.

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

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Eventual consistency
От: Sharov Россия  
Дата: 11.07.18 10:05
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>P.P.S. Да, если бы у нас была классическая реляционка


А что у Вас, NoSql или еще что?
Кодом людям нужно помогать!
Re[3]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 11.07.18 10:29
Оценка:
Здравствуйте, Sharov, Вы писали:

S>А что у Вас, NoSql или еще что?

elasticsearch же. Будем для простоты считать что все данные там (приближение хорошее, мы туда пишем и мы оттуда читаем).
На самом деле у нас есть и постгрес вдобавок, но я хочу понять как нужно работать, будь у меня только эластик в качестве БД. Ну или например кассандра.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Eventual consistency
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 11.07.18 13:13
Оценка: 4 (1) +1
Здравствуйте, Slicer [Mirkwood], Вы писали:

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

SM>Slicer


Вы пытаетесь получить строгую consistency на базе системы с delayed consistency. Если говорить в терминах acid, то речь идет об Атомарности (A).

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

В целом такие проблемы могут быть решены если у вас есть одно-узловая consistency. То есть система в целом eventual consistent, но если все запросы приходят в один и тот же узел, то выполняется требование строгой consistency.
Но, как я понимаю elastic search не обладает таким свойством.

Третий вариант — отказаться от не-ACID хранилищ для транзакционных задач. Вы по факту потребовали от системы атомарности (A) и долговечности (D) с точки зрения ACID, зачем пытаться решать задачу на системе, которая не дает таких гарантий?
Более того, внутри ACID СУБД лежит delayed consistency система с логом и данными на дисках, и СУБД применяет локальный кеша в памяти для "грязных" страниц до того как они реально записаны на диск.
Так что все, что можно изобрести поверх delayed consistency уже изобретено внутри СУБД.
Re[2]: Eventual consistency
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 11.07.18 19:00
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Вы пытаетесь получить строгую consistency на базе системы с delayed consistency. Если говорить в терминах acid, то речь идет об Атомарности (A).

В идеале да. Я готов согласиться на меньшее, если user experience при этом гарантированно не пострадает по сравнению с традиционными СУБД. Но пока по моим выкладкам получается, что пострадает.

G>1) Подождать пока consistency наступит. То есть после нажатия "сохранить" держать пользователя "сохраняю" пока не удастся получить от хранилища документ.

Не сработает, если получать подтверждение мы будем от одного узла, а ходить для продолжения работы уже на другой. Но мы могли бы ожидать подтверждения от _всех_ узлов — но для этого нужна поддержка на уровне СУБД, ведь не гулять же вручную по всем активным узлам.

G>2) ... или просто время хранения в кеше выставлять равным удвоенному среднему времени прихода подтверждения.

Ну а для экстремальных случаев мы пролетим мимо среднего.

G>В целом такие проблемы могут быть решены если у вас есть одно-узловая consistency. То есть система в целом eventual consistent, но если все запросы приходят в один и тот же узел, то выполняется требование строгой consistency.

G>Но, как я понимаю elastic search не обладает таким свойством.
Мне кажется, все же обладает — но 1) как гарантировать приход запросов на один и тот же узел (ну я писал уже что на этот счет вроде есть средство)? 2) что если узел отомрет? будет короткий момент нарушения монотонности, как минимум (хотя с этим может и смириться можно) 3) Балансировка нагрузки обламывается. Но по идее это может и пренебрежимо небольшой дискомфорт, я ранее уже упоминал, что принял к сведению такой способ.

G>Третий вариант — отказаться от не-ACID хранилищ для транзакционных задач. Вы по факту потребовали от системы атомарности (A) и долговечности (D) с точки зрения ACID, зачем пытаться решать задачу на системе, которая не дает таких гарантий?

Допустим, что у меня есть и иные требования. Скажем, к возможностям поиска (в случае эластика) или же к легкости горизонтального масштабирования.
И опять же, я могу и снять свои требования к консистентности, если мне объяснят, как без них работать пользователям.

P.S. Кстати атомарность ведь несколько не о том. Атомарность в ACID означает "либо выполнена либо нет", а не то, что все клиенты должны видеть наиболее актуальное состояние БД. А мне в общем-то не важно будет ли изменение распространено на всю БД сразу — мне главное, чтобы для юзера это выглядело так. Или не так — но как-то так чтобы он мог работать нормально без удивления.
Специалист — это варвар, невежество которого не всесторонне :)
Отредактировано 11.07.2018 19:03 Slicer [Mirkwood] . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.