【问题标题】:Relational DB in microservices微服务中的关系数据库
【发布时间】:2020-07-25 06:47:11
【问题描述】:

我有一个当前使用 PostgreSQL 数据库的单体应用程序,并且按照您对大多数关系数据库的期望设置了架构,其中各种表数据通过 user_id 上的 FK 链接回用户。

我正在尝试了解有关微服务的更多信息,我正在尝试将我的 python API 迁移到微服务架构。我对如何将较大的应用程序分解为较小的部分有合理的理解,但是,我并不完全清楚应该如何处理数据方面的事情。

我知道单个大型数据库违反微服务的一般设计原则,但我不清楚替代方案是什么。

我最大的担忧是在保存微服务数据的各个数据库之间进行级联。在一个简单的 rdb 中,我可以级联删除,数据库将处理各种表的工作。在微服务的情况下,这将如何工作?我是否需要一个单独的服务来处理跨其他服务数据库删除用户数据?

我真的不明白如何将具有关系数据库的传统应用程序迁移到微服务架构?

编辑:

澄清一下——我面临的一个具体的架构/设计问题如下:

我已将我的应用程序拆分为几个微服务。在我看来仍然相关的是:

地理定位 - 检查几何数据、PostGIS 中的记录并返回特定信息的服务。主要目的是记录特定用户的位置以供以后参考

Image - 一个简单的上传服务,用于上传图像并将元数据存储在数据库中。

Load-Image - 一个简单的服务,它根据位置等参数和年龄、性别等用户资料数据返回一组随机图像

个人资料 - 一种简单地管理用户数据(例如年龄、性别等)的服务

通常,这三个项目将在更大的数据库中各有一个表,而不是它们各自的数据库。按位置和年龄过滤图像是一个非常简单的 JOIN 和过滤器。

这样的东西如何在微服务架构中发挥作用?如果数据完全保存在不同的数据库中,我将如何设置逻辑来过滤数据?我可以复制不经常更改的数据(例如配置文件信息)并将其添加到包含图像数据(包括 user_id 和配置文件数据)的 MongoDB 文档中 - 但是,位置数据可以定期更改,并且不断更新听起来不切实际。

最好的方法是什么?还是应该只为这几个服务使用共享 RDBMS?

【问题讨论】:

  • “微服务”的任何良好表示/定义或只是其变体的许多 SO 问题都没有解决这个问题?每当您有多个必须满足约束的微服务时,它们都是更大的非微服务实现的一部分,并且您需要非微服务架构。这个问题是一个常见问题解答,尽管大多数情况下是使用特定的架构或框架提出的。但是,如果您不指定框架和其他细节,那么这与询问如何编写软件系统或编写 DBMS 并没有太大区别。这样的问题“太宽泛了”。
  • 请检查更新。我希望这能进一步澄清这个问题。它与框架无关,是一个设计问题
  • 请不要插入“EDIT”s/“UPDATE”s,编辑您的帖子以成为最好的演示文稿。您还添加了大约 19 个问号。问 1 个具体问题。在提出问题时添加问号只会使您不清楚您真正想要回答的内容。这在技术方面仍然是通用的,您刚刚添加了您的应用程序主题,它仍然过于宽泛且重复。添加所有这些问题只是反映问题太宽泛了。 How to Ask help center 您甚至期望采取什么形式得到可接受的答案? (修辞。)

标签: postgresql relational-database microservices


【解决方案1】:

在微服务架构中,我们可以选择使用每个服务的数据库或共享数据库。两种模式都有优点和缺点。每个服务架构的数据库是最佳实践,但是当单体应用程序在数据库级别具有大量功能、过程或数据库特定功能时,我们可以使用共享数据库方法,如果您有时间和带宽,我知道这不是最佳实践那么您应该为每个服务选择数据库。 由于您关心的是对单个数据库的级联,因此您需要从数据库中删除级联,并在您的应用程序中实现全局事务处理,并从该事务中执行所有与级联相关的查询。

【讨论】:

  • 我不同意。共享数据库会将您的“微服务”转变为通过数据库集成的单个系统。在这种情况下,使用分布式事务是荒谬且昂贵的。微服务设计中的绝对规则很少,但“不要使用分布式事务”就是其中之一。
【解决方案2】:

这归结为数据的重复、我们为什么需要它以及我们如何管理它。

在我们职业生涯的早期,我们被教导要在复制上下文中复制数据以实现冗余,例如,在数据库复制或备份中。我们还被告知可以以关系方式对数据进行建模,并通过约束来强制执行模型的完整性。事实上,模型的完整性是神圣不可侵犯的。没有诚信,怎么可能有一致性?答案是你不能。有点。

当您使用分布式系统和面向服务时,您这样做是因为您希望最大限度地减少交互,从而减少组件之间的耦合。然而,这是有代价的。你的架构越分散,它的耦合就越少,数据的重复就越多。这在微服务中发挥到了极致,实际上相同的数据可能以不同程度的一致性存在于许多不同的地方。

然而,在这种情况下,数据复制不是坏事,而是系统的一个基本特征。它是一种建筑风格的推动者,具有许多巨大的好处。换句话说,如果没有数据重复,你会得到更少的分布,你会得到更多的耦合,这使得你的系统构建、拥有和更改的成本更高。

所以,现在我们了解了数据重复以及我们想要它的原因,让我们继续讨论如何管理大量重复。让我们尝试一个例子:

在关系数据库中,假设我们有一个名为 Customers 的表,其中包含一个客户 ID 和客户详细信息,另一个名为 Orders 的表包含订单 ID、客户 ID 和订单详细信息。假设我们还有一个订购应用程序,如果根据 GDPR 删除客户,则需要删除所有客户的订单。

因为我们正在将系统迁移到微服务,所以我们决定创建一个名为“客户”的服务。

所以我们创建一个服务,操作如下:

  • DELETE /customers/{customerId} - 删除客户

我们使用以下操作创建另一个名为 Orders 的服务:

  • GET /orders/customers/{customerId} - 获取客户的所有订单
  • DELETE /orders/{orderId} - 删除订单

我们构建了一个用于删除客户的 UX 屏幕。 UX 首先调用订单服务来获取客户的所有订单。然后它遍历订单列表,调用订单服务删除订单。然后调用客服删除用户。

此示例非常简单,但正如您所见,除了从调用者(在本例中为用户界面)编排“删除客户”操作之外别无选择。当然,数据库中的单个原子事务不会转换为多个 HTTP/s 调用,因此有可能某些调用可能不会成功,从而使整个系统处于不一致的状态。在这种情况下,需要通过某种恢复机制来解决不一致问题。

【讨论】:

  • 谢谢你帮我清理了房间里的大象。数据重复是一个大问题,不幸的是,我表达得不够清楚!基本上,对我来说最大的损失是 JOIN 功能,当然还有级联。我想在某些情况下我可以看到 RDBMS 有意义 - 我已经更新了问题以反映我现在正在处理的特定情况
  • @maestro416 我不确定我是否同意用户界面负责协调跨上下文的数据一致性。这是非常脆弱的,也不是很有效。您通常会通过消息传递基础架构集成上下文,从而实现可靠的最终一致性模式。例如。客户上下文发送一个 CustomerDeactivated 事件/消息,订单上下文拾取该事件/消息,然后归档订单。
  • 同意@plalx,您也可以实现 BFF(前端后端),但这是另一个复杂层,会增加成本,但如果您的应用程序足够大,则值得投资。
猜你喜欢
  • 2020-12-14
  • 2021-03-30
  • 2019-12-03
  • 2020-03-22
  • 2018-05-01
  • 1970-01-01
  • 2016-04-08
  • 2019-02-18
  • 2016-11-05
相关资源
最近更新 更多