首页 > 解决方案 > 在微服务中,数据应该存储在一个服务中还是跨服务复制?

问题描述

我有一项Scheduler服务允许我添加计划任务。该服务仅在其数据库中保存触发任务时要调用的调度时间和端点。

例如,有一个Payment服务和一个EmailReminder服务。该Payment服务可以将定期付款的计划任务添加到该Scheduler服务。该EmailReminder服务可以向该服务添加电子邮件提醒任务Scheduler。当Scheduler服务中的任务被触发时,它们将被标记为done并发送到各个服务的端点以处理该任务。

在前端,它必须显示预定电子邮件提醒任务的所有信息,例如收件人电子邮件、电子邮件内容以及是否已完成。EmailReminder前端将从驻留在服务中的 API 中提取大部分信息。这很简单,因为它需要从自己的数据库中显示在 API 中的所有数据。

但是,我的困境是我应该将done状态保留在Scheduler服务的数据库中还是将这个状态保存在各个服务自己的数据库中。

如果状态存储在Scheduler服务中...

如果我在Scheduler服务中保持“完成”状态,那么每当其他服务需要知道某项任务是否完成时,它们都必须对该Scheduler服务进行 API 调用。换句话说,每次从前端调用其 API 时EmailReminder,服务都必须从服务中获取所有记录的“完成”状态。Scheduler我相信这也会在整体请求上产生额外的时间。但这样做的好处是,Scheduler服务中的数据库是判断任务是否完成的唯一真实来源。

如果状态存储在相应的服务中......

在这种情况下,EmailReminder服务不需要对服务进行额外的 API 调用Scheduler。该信息可在其自己的数据库中获得。这也意味着当服务done状态发生变化时Scheduler,它必须调度一个事件来通知所有服务更新它们的状态。然而,这样做的缺点是我基本上在两个done地方复制了同一条信息(状态);Scheduler服务和服务EmailReminder。存在数据不一致的风险。

在像我这样的微服务架构中,将此类信息存储在Scheduler服务中还是在相应的服务中更好?

标签: node.jsdatabase-designarchitecturedomain-driven-designmicroservices

解决方案


我认为您应该在这两种服务中保留该信息。

假设Scheduler请求EmailReminder发送带有 id #123EmailReminder的电子邮件,然后发送电子邮件并在本地保持“电子邮件 #123 已发送”状态,但确认失败(Scheduler未收到响应或无法保持响应)。现在Scheduler别无选择,只能重复请求。但是当EmailReminder接收到请求时,它通过它自己的状态知道邮件已经发送,并且服务可以安全地不发送邮件,而只是回复确认 - 这一次希望可以工作。

Scheduler接收到响应时,它将在本地保持“计划任务 #123 已完成”状态 - 并停止重复请求。

这也意味着当调度器服务中的完成状态发生变化时,它必须调度一个事件来通知所有服务更新它们的状态。

如果不是服务告诉它,它已经完成了,怎么Scheduler能改变它的完成度?EmailReminder

存在数据不一致的风险。

是的,这里的数据不一致意味着需要重试请求。

需要注意的一点是,服务本身也存在相同的不一致问题EmailReminder,因为可以发送电子邮件,并且错误会阻止本地状态正确更新。因此,电子邮件总是有可能被发送两次(“至少一次”发送,或者您可以通过在发送前更改状态来选择“最多一次”) - 但这种方式风险较低。


推荐阅读