Комментарии 10
Отличная статья, спасибо!
В процессе чтения много раз приходила в голову мысль: а не было бы существенно проще, если бы все части системы, нуждающиеся в высоких гарантиях согласованности, опирались не на личные маленькие базки, а на одну большую?
Навскидку выглядит так, что Distributed SQL базы (CRDB, YDB) вполне могут с этим помочь.
Если использовать одну большую базу, то будет слишком велик соблазн каким-то сервисам самовольно влезать в данные других сервисов и вносить туда изменения, которых не ожидают владельцы данных (например, нарушать какие-то правила организации данных). Чтобы такого не было каждый сервис хранит свои данные изолированно от других и предоставляет наружу интерфейс для взаимодействия :)
Этот паттерн мне известен, я предлагаю не считать его серебряной пулей, а попробовать критично переосмыслить его применимость при столкновении с требованием строгой согласованности на раздельных базах.
Это требование "кричит", что система распилена на части в неподходящем месте, как итог разработчики сталкиваются с необходимостью решать ещё более сложные проблемы, чем в ситуации когда база общая — собственно об этих проблемах вся ваша статья.
Понятно, что бывают ситуации, когда система уже распилена, а требование согласованности пришло постфактум — тут простых решений нет, но на этапе проектирования я бы рекомендовал делить систему на части, именно опираясь на требования согласованности данных.
Кстати, пришла тут в голову мысль. Можно доступы на базе с помощью ACL разделять, чтобы соблазна лезть в чужие данные не было.
Решать алгоритмические проблемы эмпирическими методами может быть дорого, долго и неправильно. Может стоит откатиться на шаг назад и посмотреть на проблему сверху: какие есть теоретические наработки и стандарты в вашей области для организации распределенного процессинга, как проводится верификация решения?
Полезная статья для тех, кто в теме и вынужден решать подобные проблемы.
Однако, простая фоновая джоба хоть на обработке хоть на отсылке, да ещё однопоточная, просто не будет справляться при действительно высоких нагрузках. И начнется следующий этап борьбы - распараллеливание джоб и опять решение вопросов строгой упорядоченности и неповторов при успехе и повторов при определенных ошибках.
Кроме того, в статье возможно умышленно опущены вопросы идемпотентности ибо я слабо себе представляю чтобы сервис при схеме запрос-ответ молча проглотил повтор запроса и не выдал ответа.
Было бы круто в конце статьи увидеть обзор решений, которые частично или полностью решают подобные проблемы в распределенных системах с использованием асинхронного взаимодействия с брокерами сообщений и/или шинами данных.
Например, на сайте Temporal пример с переводом денег между счетами описан в качестве демо того как эта проблема там решается.
2-фазовые коммиты, всё как мы любим =)
Как будто не учтён ещё кейс, когда все ОК, но в момент финального ack все сломалось и сообщение ушло в retry. А затем при повторной обработке кто-то успешно купит две пиццы вместо одной :).
Нужно ещё видимо где-то хранить и проверять статус основного события, обработано оно или нет и проверять его перед обработкой.
Консистентность в конкуретной среде: как не захлебнуться в потоках данных