>我目前正在尝试进入微服务架构,但我遇到了数据一致性问题。我读过,在多个微服务之间复制数据被认为是一个好主意,因为它使每个服务更加独立。
但是,我不知道在以下情况下该怎么做才能提供一致性:
- 我有一个客户服务,它有一个注册客户方法。
- 当我注册客户时,我想通过 RabbitMQ 发送消息,以便其他服务可以获取此信息并存储在其数据库中。
我的代码看起来像这样:
...
_dbContext.Add(customer);
CustomerRegistered e = Mapper.Map<CustomerRegistered>(customer);
await _messagePublisher.PublishMessageAsync(e.MessageType, e, "");
//!!app crashes
_dbContext.SaveChanges();
...
所以我想知道,当应用程序发送消息但无法保存数据本身时,我如何处理这种情况?当然,我可以交换 DbContextSave 和 PublishMessage 方法,但麻烦仍然存在。我的数据存储方法有问题吗?
是的。您正在执行双重持久性 - 数据库中的持久性和持久队列中的持久性。如果一个成功了,另一个失败了,你总是有麻烦。有几种方法可以处理此问题:
-
保留在数据库中,然后执行更改数据捕获 (CDC(,以便使用数据库预写日志 (WAL( 中的数据在第二个服务数据库中使用实时流式处理创建具体化视图
-
保留在持久队列和缓存中。使用实时流式处理将两个服务中的数据保留。如果数据在缓存中可用,则从缓存中读取数据,否则从数据库读取数据。这将允许在写入后读取。即使在最坏的情况下写入缓存失败,数据也会在几秒钟内通过流式传输到数据库中
与 RMQ 相比,NServiceBus 在许多场景中确实支持持久分布式事务。也许您可以考虑使用该功能来确保在发生故障时保存或回滚两个上下文,如果您可以使用 NServiceBus 而不是 RMQ。
我认为您正在寻找的解决方案是发件箱模式,与您的业务数据位于同一数据库中,有一个与事件相关的数据库表,这允许它们在同一个数据库事务中提交,然后后台工作线程循环将事件推送到 MQ