Возможная согласованность в архитектуре на основе микросервисов временно ограничивает функциональность
Я проиллюстрирую свой вопрос в Твиттере. Например, Twitter имеет микросервисную архитектуру, что означает, что разные процессы находятся на разных серверах и имеют разные базы данных.
Появляется новый твит, сервер А хранит в своей базе данных некоторые данные, генерирует новые события и запускает их. Сервер B и C не получили эти события в этот момент и не хранили ничего в своих базах данных и ничего не обрабатывали.
Пользователь, создавший твит, хочет отредактировать его. Для достижения этого все три службы A, B, C должны были обработать все события и сохранить их для сохранения всех необходимых данных, но службы B и C пока не согласованы. Это означает, что в настоящее время мы не можем предоставить функции редактирования.
Как я вижу, возможный обходной путь может заключаться в переходе к немедленной согласованности, но это отнимет все преимущества архитектуры на основе микросервисов и, вероятно, может вызвать проблемы с жесткой связью.
Другой обходной путь - ограничить действия пользователя на некоторое время, пока данные не будут согласованы во всех необходимых службах. Вероятно, решение зависит от клиента и его бизнес-требований.
И еще один обходной путь - добавить дополнительную логику или, возможно, сервис D, который будет хранить изменения как действия пользователя и применять их к данным только тогда, когда они будут согласованы. Недостаток - очень повышенная сложность системы.
И есть двухфазные коммиты, но это 1) не очень надежный 2) медленный.
Я думаю, что медлительность является огромным недостатком в случае таких нагрузок, как Twitter. Но, вероятно, это можно решить, в то время как недостаток надежности не может, опять же, без повышенной сложности решения.
Итак, вопросы:
- Есть ли хорошие решения для иллюстрированной ситуации или только те вещи, которые я упомянул как обходные пути? Может быть, какие-то программные платформы или базы данных?
- Я что-то неправильно понял, а некоторые обходные пути не верны?
- Есть ли другой подход, кроме возможной согласованности, который гарантирует, что все данные будут сохранены, а все необходимые действия будут выполнены другими службами?
Почему для этого варианта использования была выбрана конечная согласованность? Как я вижу, на данный момент это единственный способ гарантировать, что некоторые данные будут сохранены или какое-то действие будет выполнено, если мы говорим о подходе, основанном на событиях, когда некоторые службы начнут свою работу, когда какое-либо событие будет запущено, и следуя моему примеру, это событие будет "твит создан". Таким образом, в случае, если сервисы B и C не работают, мне нужно иметь возможность успешно выполнять действия, когда они снова будут работать.
Я хотел бы добиться следующих целей: надежность, способность выдерживать высокие нагрузки, адекватная сложность решения. Любые ссылки на любые связанные темы будут очень благодарны.
Если есть естественные ограничения этого подхода и то, чего я хочу, не может быть достигнуто с помощью этой парадигмы, это тоже хорошо. Мне просто нужно знать, что эта проблема действительно еще не решена.
2 ответа
Это все о компромиссах. С возможной последовательностью в вашем примере это может означать, что пользователь не может редактировать в течение, возможно, нескольких секунд, так как большинство возможных последовательных технологий не займет слишком много времени для репликации данных между узлами. Так что в этом случае это абсолютно приемлемо, так как пользователи довольно медлительны в своих действиях.
Например:
MongoDB согласован по умолчанию: операции чтения и записи выдаются первичному члену набора реплик. Приложения могут при желании читать из вторичных реплик, где данные в конечном итоге согласованы по умолчанию.
Другая альтернатива, которая становится все более популярной, - это использовать потоковую платформу, такую как Apache Kafka, где ваша архитектура решает, насколько быстро потребитель потока будет обрабатывать данные (для возможной согласованности). Поскольку потоковая платформа очень быстрая, в большинстве случаев только скорость вашего потокового процессора делает данные доступными в нужном месте. Таким образом, мы говорим о миллисекундах, а не о секундах в большинстве случаев.
Ключевым моментом в такого рода архитектурах является то, чтобы каждая служба была автономной, когда дело доходит до записи: она может взять на себя запись, даже если ни одна из других служб уровня приложения не работает.
Итак, в примере сервиса, похожего на твиттер, вы бы смоделировали его как
Service A manages the content of a post
Поэтому, когда пользователь делает сообщение, в БД службы А происходит запись, и с этого момента сообщение можно редактировать, потому что редактирование — это просто запрос к А.
Если есть какая-то другая служба, которая использует события изменения «публикации контента» из A и после того, как событие «новая публикация» предоставляет некоторые функции, эта функциональность не будет доступна до тех пор, пока эта служба не увидит событие (ура, тавтологии). Но это всего лишь физика: солнце могло стать сверхновой пять минут назад, и мы не можем предпринять никаких действий (да и не могли), пока не «увидим свет».