node.js - 在微服务中,数据应该存储在一个服务中还是跨服务复制?
问题描述
我有一项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
服务中还是在相应的服务中更好?
解决方案
我认为您应该在这两种服务中保留该信息。
假设Scheduler
请求EmailReminder
发送带有 id #123EmailReminder
的电子邮件,然后发送电子邮件并在本地保持“电子邮件 #123 已发送”状态,但确认失败(Scheduler
未收到响应或无法保持响应)。现在Scheduler
别无选择,只能重复请求。但是当EmailReminder
接收到请求时,它通过它自己的状态知道邮件已经发送,并且服务可以安全地不发送邮件,而只是回复确认 - 这一次希望可以工作。
当Scheduler
接收到响应时,它将在本地保持“计划任务 #123 已完成”状态 - 并停止重复请求。
这也意味着当调度器服务中的完成状态发生变化时,它必须调度一个事件来通知所有服务更新它们的状态。
如果不是服务告诉它,它已经完成了,怎么Scheduler
能改变它的完成度?EmailReminder
存在数据不一致的风险。
是的,这里的数据不一致意味着需要重试请求。
需要注意的一点是,服务本身也存在相同的不一致问题EmailReminder
,因为可以发送电子邮件,并且错误会阻止本地状态正确更新。因此,电子邮件总是有可能被发送两次(“至少一次”发送,或者您可以通过在发送前更改状态来选择“最多一次”) - 但这种方式风险较低。
推荐阅读
- postgresql - PostgreSQL - select..where:值可能为空时的语法
- latex - LyX/LaTeX 文件是否太大而无法创建 PDF?
- linux - 如何修复 JavaFX 运行时组件丢失?
- javascript - 在 html 中预定义 jquery 变量
- java - 如何实施监控应用程序
- google-cloud-platform - gcloud beta 功能部署 ha 命令不更新 HA(家庭自动化)功能 URL
- visual-studio-code - VSCode 中 JSX 标签内的片段
- python - 使用其他功能克隆 tkinter 按钮
- java - 检查数据库中密码的功能
- java - 如何在每行中添加 3 个按钮