Обработка синхронизации данных в реальном времени между микросервисами с помощью очередей rabbitmq

#architecture #rabbitmq #microservices #devops #eventual-consistency

Вопрос:

Мы настроили наш микросервис на использование rabbitmq очередей для обработки любых предстоящих данных.

Итак, у нас есть service A , service B , service C и service D .

Когда приходит запрос на создание пользователя service A , он создает пользователя и помещает событие в newUserIsCreated очередь.

Теперь service B и service C необходимо обновить свою базу данных для вновь добавленного пользователя.


Проблема:

Что делать, если создание пользователя завершится неудачно в любом service B и service C .

Возможными сценариями сбоя могут быть сбой проверки или сбой service B service C и.

Существует также проблема при service D попытке доступа к одному и тому же пользователю.

Чем бы service B и service C ответили? Потому что к тому времени у них не будет вновь созданного пользователя.


Подводить итоги,

Как справиться с ошибкой проверки или любым другим сбоем между этими службами?

Что делать, если требуется синхронизация в реальном времени? (обработка очередей может занять некоторое время)

Комментарии:

1. Я думаю, что в вашем случае использования вместо rabbitmq у вас должен быть другой service-x , который вызывает три другие службы, если кто-либо из служб отключен или не отвечает, вы service-x должны иметь возможность выполнять операции отката.

Ответ №1:

Вы могли бы B и C (и любая другая служба, которая должна подтвердить, что пользователь создан) опубликовать сообщение с подтверждением в RabbitMQ, которое будет принято A ; A затем не подтверждает, что пользователь был создан, пока он не получит подтверждения. Это не является надежным: есть все шансы, что он везде преуспел, но A не получил подтверждения вовремя. Для этой (в идеале редкой) ситуации у вас может быть процесс очистки.

Однако стоит отметить, что такого рода синхронные отношения в основном переопределяют запрос/ответ через очередь сообщений, поэтому, если идти по этому пути, почему бы просто не выполнить прямой запрос/ответ (например, HTTP или gRPC)?

Если у вас есть операция, которая должна повлиять на несколько служб, часто бывает полезно смоделировать ее как сагу, которая будет отправлять запросы различным службам и обрабатывать сбои (и, возможно, откажется, если было слишком много сбоев, откатив внесенные изменения). Сохранив состояние саги (например , обновлено B , но C еще не подтверждено обновление), ее можно запросить.

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

Комментарии:

1. Это надежный ответ. Я бы добавил, что для несколько похожего приложения, в котором периодические отключения были фактом жизни, мы создали микросервис «ConsistencyAudit» (отдельно), который подписывался на ...created события из нескольких служб и следил за любыми пропусками, а затем предпринял некоторые действия, чтобы уведомить администратора. Простой, отдельный, производительный и (как оказалось) ненужный, но был создан для аналогичных задач.

2. Да, в более ориентированной на события системе я бы выбрал именно это.