LINUX.ORG.RU

возможна ли надёжная передача сообщений?

 ,


0

2

Начал осмысливать микросервисы и быстро стало ясно, что есть шаблон, который повторяется.

Есть два субъекта. Допустим, я и мой банк. Мне надо перевести деньги. Как сделать это надёжно, при условии, что у банка может упасть база, что моя программа клиент-банк может упасть, и что связь тоже может упасть.

Я нагуглил теорему CAP (латиницей), которая говорит, что вообще говоря, это можно сделать только ценой отсутствия гарантии обслуживания. Но это и не теорема, а так, наблюдение, да и мало ли что пишут в Википедии? Я уже не раз сталкивался с тем, что там пишут всякий бред.

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

В конечном итоге я хочу, чтобы было три знания.

  • Известно, сколько денег у меня есть.
  • Я знаю, что эти сведения у меня и у банка совпадают
  • Банк знает, что эти сведения у меня и у банка совпадают

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

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

Ясно, что я где-то туплю, но не понимаю, где.

★★★★★

Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от anonymous

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

torvn77 ★★★★★
()
Последнее исправление: torvn77 (всего исправлений: 2)
Ответ на: комментарий от torvn77

Что-то твои редакции не приходят последовательно, я потерял промежуточные. :-)

anonymous
()
Ответ на: комментарий от den73

Если бы это были звёзды, можно увидеть, что звезда взорвалась, через фиксированное число лет. Это только потому, что божественный вакуум гарантирует доставку света (если не считать тёмных газопылевых туманностей).

Распространение не тождественно доставке. В твою наблюдалку влетит метеорит - и ничего не зафиксируется.

Сеть же не гарантирует ни доставки, ни сроков доставки.

Протоколы и алгоритмы предназначены для решения конкретных задач в конкретных условиях конкретной модели. Если дядя Вася из соседней квартиры стабильно обрезает кабель эзернет, единственный канал связи вас с провайдером, этa проблемa решается за пределами модели OSI.

seiken ★★★★★
()
Ответ на: комментарий от seiken

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

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

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

Вот вопрос из SO в моём направлении:

https://stackoverflow.com/questions/49997082/is-it-possible-to-detect-that-a-...

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

Допустим, в нашей модели это будет банк. Но надо думать дальше.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)

Верно, гугли «теорему о двух генералах» для доказательства.

Все распределённые протоколы - это лишь некоторые вероятностные приближения к картине «обе стороны точно знают результат их взаимодействия».

Пример CAP без A - это любой двухфазный/трехфазный коммит, которые часто применяют для клиент-банк взаимодействия. Т.е. знание о балансах консистентно на всём протяжении, кроме времени коммита.

allter149
()

1-е правило. Никому не доверяй. Предположим, что у банка есть А) Хранилище где лежат золотые слитки. Б) Кредиторы Ц) Депозиты.

Теперь у банка сгорает датацентр (я про Сбербанк) и у них нет бумажных копий документов - они сгорели. Теперь ты приходишь с своими бумажками в Банк и просишь у него вернуть твой депозит.

А вот те кто брал кредит придут? Предположим что тебе поверят, но ясно что все кто открывал депозит не смогут получить золото. Докажи что твои бумажки НАСТОЯЩИЕ?

dem ★★
()
Ответ на: комментарий от allter149

P.S. тот же 2/3 фазный коммит можно рассматривать и как AP и CA, в зависимости от того, как используется знание о счетах в процессе коммита..

allter149
()

Стоит почитать про задачу о Византийских генералах, про алгоритм raft, про то, что такое консенсус в распределенной системе. Еще про логические и векторные часы.

Но это не совсем про клиента и банк. Мне кажется, банк скорее про консистентность в ущерб доступности. Т.е. банк как целостная система может не ответить за заданное время или вернуть сообщение об ошибке, но не вернет устаревшее состояние счета после выполнения перевода. Внутри банка будут эти самые консенсусы, raft и прочее.

Рекомендую почитать про идемпотентные API, недавно на хабре была отличная статья от коллег из Яндекса. Можно послать банку команду на перевод, команда может обломаться из-за сети, можно команду повторить. Хороший API хорошего банка не переведет деньги второй раз, это решается идентификаторами запросов и версиями состояния на сервере.

stateofart
()
Ответ на: комментарий от den73

1. Ты точно хочешь распределенные транзакции.

2. В описанной тобой системе можно обойтись без них.

ya-betmen ★★★★★
()

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

maxcom ★★★★★
()
Ответ на: комментарий от dem

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

anonymous
()
Ответ на: комментарий от anonymous

Это было с Диалог Оптим где я работал. Но тут о том что спрашивал ТС я сказал, что протокол можно НАРУШИТЬ.

dem ★★
()

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

См. https://ru.wikipedia.org/wiki/Задача_двух_генералов

SZT ★★★★★
()
Ответ на: комментарий от den73

КОторая опять же заканчивается этим «я понял, что ты понял».

После завершения перевода банку совсем не обязательно знать что клиент принял сообщение о том что перевод выполнен. Достаточно дать клиенту возможность в любой момент в будущем (например при следующем сеансе связи) спросить «Эй, Банк, какой статус у моей операции №000001?».

cPunk ★★
()

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

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

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

Если пакет до банка дошёл, он его обработал и ответил, что деньги переведены. Если пакет не дошёл и соответственно ответа клиенту не было, клиент шлёт пакет повторно с тем же самым id.

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

shell-script ★★★★★
()
Ответ на: комментарий от shell-script

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

И из этого знания можно уже начинать пытаться строить распределённые системы.

den73 ★★★★★
() автор топика

Варианта ответа 2.

1) Общий случай. Отвечает на ваш вопрос по смыслу, но не по содержанию (иначе, говоря, ваш пример - говно).

Я знаю, что у меня X -> я отправляю банку информацию X, подписанную своим ключом. Теперь банк знает, что у меня Х. Банк отправляет информацию о получении Х мне, подписанную своим ключом. Теперь, у меня два варианта.

а) Если я не получаю подтверждение от банка за отведённый срок, я вновь пересылаю X.

б) Если я получил подтверждение от банка, я ничего не делаю, т.к. всем безразлично, получил я подтверждение от банка или нет.

2) Частный случай. В случае общения клиента с банком, вы вообще не должны хранить Х, где Х - количество денег или любая другая информация о счёте, кроме его номера. Вся информация которую получает клиент носит справочный характер. Вместо этого Х хранит исключительно банк. А вы лишь вызываете удалённые процедуры с некоторыми параметрами.

[cod=cpp] transfer_mоney(me, my_friend, 10);

А банк сам уже решает, допустима данная операция или нет.

anonymous
()
Ответ на: комментарий от anonymous

Поломалась разметка, плохо прочитал инструкцию. Ну и ладно.

anonymous
()
Ответ на: комментарий от dem

Это уже следующий уровень сложности.

den73 ★★★★★
() автор топика
Ответ на: комментарий от maxcom

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

den73 ★★★★★
() автор топика
Ответ на: комментарий от shell-script

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

anonymous
()

MQTT там вроде можно даже уровень надежности выбирать

Int0l ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.