#database #transactions #microservices #data-consistency
#База данных #транзакции #микросервисы #согласованность данных
Вопрос:
В настоящее время я пытаюсь разобраться в архитектуре микросервисов, и я столкнулся с проблемой согласованности данных. Я читал, что дублирование данных между несколькими микросервисами считается хорошей идеей, потому что это делает каждый сервис более независимым.
Однако я не могу понять, что делать в следующем случае, чтобы обеспечить согласованность:
- У меня есть служба поддержки клиентов, в которой есть метод RegisterCustomer.
- Когда я регистрирую клиента, я хочу отправить сообщение через RabbitMQ, чтобы другие службы могли получать эту информацию и сохранять в своей базе данных.
Мой код выглядит примерно так:
...
_dbContext.Add(customer);
CustomerRegistered e = Mapper.Map<CustomerRegistered>(customer);
await _messagePublisher.PublishMessageAsync(e.MessageType, e, "");
//!!app crashes
_dbContext.SaveChanges();
...
Итак, я хотел бы знать, как я могу справиться с таким случаем, когда приложение отправляет сообщение, но не может сохранить сами данные? Конечно, я мог бы поменять местами методы DbContextSave и PublishMessage, но проблема все еще существует. Что-то не так с моим подходом к хранению данных?
Ответ №1:
ДА. Вы выполняете двойную сохраняемость — сохраняемость в БД и долговременную очередь. Если один завершится успешно, а другой завершится неудачей, у вас всегда будут проблемы. Есть несколько способов справиться с этим:
-
Сохраняйте в БД, а затем измените сбор данных (CDC) таким образом, чтобы данные из журнала предварительной записи БД (WAL) использовались для создания материализованного представления во второй службе DB с использованием потоковой передачи в реальном времени
-
Сохраняется в долговременной очереди и кэше. Используя потоковую передачу в реальном времени, сохраняйте данные в обеих службах. Считывать данные из кэша, если данные доступны в кэше, в противном случае считывать из базы данных. Это позволит выполнять чтение после записи. Даже если в худшем случае произойдет сбой записи в кэш, в течение нескольких секунд данные будут в БД посредством потоковой передачи
Ответ №2:
NServiceBus действительно поддерживает длительную распределенную транзакцию во многих сценариях по сравнению с RMQ. Возможно, вы можете рассмотреть возможность использования этой функции, чтобы гарантировать, что оба контекста сохраняются или откатываются вместе в случае сбоев, если вы можете использовать NServiceBus вместо RMQ.
Ответ №3:
Я думаю, что решение, которое вы ищете, — это шаблон исходящих, в той же базе данных, что и ваши бизнес-данные, есть таблица базы данных, связанная с событием, это позволяет зафиксировать их в той же транзакции базы данных, а затем фоновый рабочий цикл отправляет событие в mq