Микросервисы, CQRS: возможная согласованность и строгая согласованность (чтение после записи согласованность)
Используя CQRS и хранилище событий, хореография между микросервисами обеспечивает конечную согласованность, при которой изменениям в одном микросервисе требуется немного времени для распространения на другие нисходящие системы (в основном, на другие микросервисы), которые связаны между собой. Какие есть варианты, если данные настолько важны, что оба микросервиса должны иметь строгую согласованность данных? Один из вариантов, который я могу придумать, - это запись через Cache, подобную сетке данных, но это было бы очень хрупко, особенно в распределенной системе.
3 ответа
В таком случае подумайте о теореме CAP. Согласно Википедии, "теорема CAP гласит, что при наличии сетевого раздела нужно выбирать между согласованностью и доступностью. Обратите внимание, что согласованность, как определено в теореме CAP, весьма отличается от согласованности, гарантированной в транзакциях базы данных ACID."
Поскольку у вас есть 2 микросервиса, ваша система определенно должна быть терпимой к разделам, и вам остается либо A (доступность), либо C (согласованность). Если вы хотите перейти с C, то ваша система будет страдать с точки зрения доступности. Когда запрос поступает в Microservice A, вам не следует отправлять клиенту сообщение об успешном завершении, пока A не получит ответ от Microservice B о том, что данные были успешно сохранены. Таким образом, вы можете достичь согласованности, пожертвовав доступностью.
Сильное согласие сложно в распределенных сервисах и еще сложнее с микросервисами, потому что они владеют своими данными. Это означает, что вы можете иметь сильное согласие только внутри микросервиса.
Тем не менее, вы можете смоделировать критические операции как сложный процесс, используя Saga/Process Manager. Это означает, что вы используете Saga для организации завершения операции способом, приемлемым для вашего бизнеса. Например, вы можете использовать что-то вроде шаблона Reservation
Этот шаблон позволяет упорядоченно управлять процессом выделения ресурсов путем реализации двухпроходного протокола, что несколько похоже на двухфазную фиксацию. Во время первого прохода инициатор просит каждого участника зарезервировать себя. Если инициатор получает ОК от всех задействованных служб - в течение тайм-аута - он запускает второй проход, подтверждая бронирование всем участникам.
В этом случае, когда любое действие начинается с Учетной записи, оно может получить текущее состояние из Микросервиса Процентов, таким образом, вы всегда будете синхронизированы, но вы будете делать сервис зависимым друг от друга, так что, когда Интерес Сервиса не будет работать, Сервис Аккаунта будет эффективно закрыт.,
Рассматривая ваш вопрос, я думаю, что вам нужно подумать о том, настолько ли важна согласованность (я задаю этот вопрос, как если бы мы исходили из монолита или транзакционного фона, мы склонны думать, что согласованность существует).
Например: скажем, если вы размещаете заказ на Amazon и вам нужно отправить идентификатор клиента, есть случай, когда вам нужно проверить, действителен ли идентификатор клиента или нет.
это сделает Службу заказа зависимой от службы поддержки клиентов.
Другое решение этого вопроса - при размещении заказа не проверять идентификатор клиента, а проверять его на событии OrderPlace и предпринимать необходимые действия.
Поэтому постарайтесь сделать так, чтобы система лучше реагировала на возможное состояние, а не фокусировалась на транзакциях в микросервисе. Но если да, то есть потребности, которые очень важны для бизнеса, сделайте их зависимыми
Сильная последовательность не может быть достигнута в ландшафте микросервисов. После того, как вы сломаете хранилище данных, вы потеряете сильную согласованность.
В нашем приложении нам еще предстоит найти, как достичь 100% гарантированной конечной согласованности, без использования какого-либо механизма опроса / планировщика для восстановления после сбоя системы / сети.
Вы можете использовать Kafka или Kinesis для определения согласованности событий между двумя микро-сервисами для критических обновлений данных. Например, реакция Micro Service 1 [MS1] на событие вызывает соответствующее сообщение в теме, которое затем мгновенно читается MS2.
Другое преимущество этого подхода состоит в том, что если существует множество MS, зависящих от реакции MS1, то все другие MS могут получить это событие.
Если события завершены и идемпотентны, то вы также можете включить сжатие журналов (хотя и не обязательно), чтобы всегда получать последнюю копию в течение определенного периода времени.
Примечание: Тем не менее, убедитесь, что вы используете один раздел только в теме Kafka, так как гарантии заказа в Kafka относятся только к разделу или всегда добавляйте ключи к сообщениям, чтобы они попадали в один и тот же раздел.
В двух словах,
- Kafka / Kinesis как организатор событий / посредники между микросервисами
- Отдельный раздел и / или сообщения с ключами (с сжатием журнала)
- Удержание [на основе требований]
- 3 х Репликация [доступность данных]
- acks = all [высокий уровень согласованности данных]