没有数据重复的微服务


19

我发现即使对于最简单的微服务设计,也很难避免重复数据或共享数据库,这让我觉得我缺少了一些东西。这是我面临的问题的基本示例。假设某人正在使用Web应用程序来管理库存,那么他们将需要两项服务:一个用于管理物品和库存数量的库存,以及一个用于管理用户数据的用户服务。如果我们要审核谁库存数据库,可以将用户ID添加到库存服务的数据库中,作为最后按价值库存的库存。

使用该应用程序,我们可能希望查看所有即将用完的物品,以及上次库存者的清单,以便我们可以要求他们再次进行库存。使用上述架构,将向库存服务发出请求,以检索数量小于5的所有商品的商品详细信息。这将返回包含用户ID的列表。然后,将对用户服务进行单独的请求,以获取从库存服务获得的用户ID列表的用户名和联系方式。

这似乎效率很低,并且在我们向不同的服务API发出多个请求之前,不需要更多的服务,而这些服务API又会进行多个数据库查询。一种替代方法是复制库存数据中的用户详细信息。当用户更改其联系方式时,我们将需要通过所有其他服务来复制更改。但这似乎与微服务的有限上下文概念不符。我们还可以使用一个数据库,并在不同的服务之间共享它,从而解决集成数据库的所有问题

什么是实现此目的的正确/最佳方法?


5
欢迎来到微服务的悖论。看起来会使事情变得简单的事情实际上会使事情变得更加复杂。
罗伯特·哈维

“正确”的方式与以往一样:找出最适合您的特定目标的方式。
罗伯特·哈维

1
@RobertHarvey总是这样,但是我试图理解教科书微服务的方式。一旦了解了它在理想世界中的工作原理,我将很高兴对其进行更改以适合我的用例。
Geraint Anderson '18

1
但是您是根据效率来提出问题的,这是一项非功能性的软件要求。解决效率问题的方法是直接询问数据库。
罗伯特·哈维

1
我正要写一个与您完全相同的问题。对于相当简单的Web应用程序,MSA仍然没有优势。我认为在许多情况下,无需使事情变得如此复杂就可以实现模块化。
Glasnhost

Answers:


10

我完全错过了要求您重复的地方。

微服务的中心原则是使服务成为单一权限。这意味着清单和用户管理可以完全分开。我会设计用户管理,以便它甚至不知道库存系统是否存在。

但是,我会设计库存系统,以便除用户ID之外,它从不存储有关用户的任何信息。这样可以解决您传播用户信息更改的问题。

至于需要库存信息和用户信息(例如日志,审计和打印输出)的东西,它们不会随着信息的变化而更新。他们是过去的记录。同样,您不会传播更改。

因此,在每种情况下,当您想要最新的用户信息时,都可以询问用户信息服务。


@杰琳特:您能更详细地说明系统中正在发生哪种复制吗?
罗伯特·哈维

1
谢谢。重复是指将用户的联系方式复制到库存服务,但您已解决了此问题(即不是必需的)。从单个关系数据库(我可以通过连接获取清单数据和用户数据)转而进行两个不同的API调用似乎是违反直觉的,在第二个API调用中,直到第一个返回结果之前,第二个才可以开始。但是我想这是我是否使用微服务或其他服务的评估的一部分。
Geraint Anderson

如果数据库同时管理两者,那将是相同的技巧。您不会将用户信息复制到清单表中。您给它一个外键。用户ID在所有服务中都执行相同的工作。使其独特。
candied_orange

It seems counter-intuitive to move from a single relational database where I could get the inventory data and the user data with a join请记住,“理想情况下”,每项服务应设有一家商店(或更多!)。因此,“边界”之间没有诸如“联接”之类的东西。原因很简单,DB在服务之间生成耦合。与@CandiedOrange建议不同,我认为我们可以将最少的数据从一项服务复制到另一项服务。我指的是不太可能更改的数据。如果这种改进提高了效率和性能(并且都需要),那么“优点”可能会抵消“缺点”
Laiv

@GeraintAnderson我的意思是,如果您需要效率(按定义,这是一项非功能性要求),则有多种方法可以实现。即从清单服务请求数据页面(如10个元素),占用每个页面,并使用该页面向用户服务请求数据,最后进行汇总。这样,您可以在利用独立服务的并行性的同时保持界限。即使这样,也不要担心,直到您将其确定为必须解决的应用程序的真正瓶颈为止-在​​1秒的夜间工作中等待额外的1/2秒对任何人都没有关系。
Delioth

11

我发现很难避免数据重复...。

根据Microsoft关于微服务体系结构的电子书,数据复制没有错。基本上,重复数据会增加服务之间的分离,因此会增强它们作为单一权限的作用。相关文章:

最后(这是构建微服务时大多数问题出现的地方),如果您的初始微服务需要最初由其他微服务拥有的数据,则不必依赖对该数据进行同步请求。相反,通过使用最终一致性(通常通过使用集成事件),将该数据(仅需要的属性)复制或传播到初始服务的数据库中。


1
我完全不同意。它使维护变得更加困难。它使您可以在必须添加,更新或删除某些东西时在微服务之间实现事务。如果要防止单点故障,可以使用请求或任何其他类型的缓存。
艾伦·塞雷布

1
@AlanSereb很难维护,但关键是有时您别无选择。例如,如果需要在两个数据库中的对象之间建立FK,该怎么办?在本地数据库中进行查询时,确保一致性的唯一方法是进行数据复制。看一下:stackoverflow.com/a/4452586/2255491
David D.

我同意。另一种很好的方法是采取事件来源路线。并通过事件管道执行所有变异
艾伦·塞雷布

4

将向库存服务发出请求,以检索数量小于5的所有物料的物料详细信息。这将返回包含用户ID的列表。然后,将对用户服务进行单独的请求,以获取从库存服务获得的用户ID列表的用户名和联系方式。

完全同意。

当然,在一个整体中,您可以拥有一个库存模型,您可以查询相关项目,将其输入用户模型并获得相同的数据。

或者,如果您将它们放在同一个关系数据库中并编写SQL,并且该数据库将使用库存表和用户表,则可以做得更神奇,并且可以得到想要的数据。

不管你怎么做,有什么地方有一些代码,这些代码本质上是从清单系统中获取用户ID的列表,然后将其输入用户系统并编译数据列表。

您需要回答的问题是有关性能和维护以及其他“软”质量的问题。

微服务的主要好处是扩展。如果一台计算机上有一万个用户,并且有点慢,则可以添加另一台计算机,系统速度将提高一倍。再增加8个,速度快十倍。(线性缩放可能是乐观的,但这是理想的选择,而不是不合理的希望。)

这是每项服务。如果清单系统是瓶颈,那么它不仅仅用于有关用户的报告,还可以在该服务中添加更多计算机。。机器也可以专门化;该服务需要大量内存,该服务需要大量计算,并且需要更多cpu。

如果您不需要扩展,微服务还有另一个好处:它们是模块化的。当然,单片应用程序也可以是模块化的,并且您具有规范化的数据库和...但是在实践中,模块之间的墙在最好的情况下就像玻璃墙,而在最坏的情况下就像沙子一样。微服务由实心钢分隔。

如果您的用户系统从字面上着火,那丝毫不会影响您的库存系统。您将无法打印出有关谁库存了什么东西的漂亮报告,但是客户将能够在知道库存物品在那里的情况下安全地下订单。

而且,您不会像在关系数据库(*)中那样重复微服务中的数据。在关系数据库中,您可以执行join,相当于将列表合并为上述代码。

您还可以添加一个视图,等效于添加一个为您执行合并的新服务;这将导致三个请求;一个服务到新服务,然后该服务执行原来的两个服务。关系数据库中有一些花哨的东西可以优化视图,必须在服务级别上实现。您不会“免费”获得它。

缓存与数据复制的区别在于,如果两个值不匹配,您就会知道哪个错误。它经常用于微服务中,以牺牲一致性(CAP定理)为代价来提高可用性。由于关系数据库完全在一致性的基础上提高了可用性,因此在它们中很少见。我要说的是,微服务没有内在的特性可以使缓存变得更容易,但实际上缓存是最主要的考虑因素,它可以使微服务中的缓存变得更容易

(*)如果在微服务群中复制数据有意义,那么在等效的关系数据库中可能有意义。


3
在“不要在微服务中重复数据”部分之前,我真的很喜欢您的回答。我认为在某些情况下,数据复制是正确的方法。它提高了容错能力和自治性。如果用户服务出现故障,库存服务仍可以显示低库存清单以及最后库存的人。
庞贝

1
@peterpompeii我称其为缓存,而不是数据重复。数据复制是指在一个位置有两个位置要更新的地方,在一个位置有一个地方进行缓存,然后自动传播到另一个地方。我还说的不仅仅是关系。如果在关系数据库中复制数据有意义,那么在微服务中有意义。我认为我们同意,这一部分可能会更清楚,但是我现在只有一部电话,因此现在不会更新文本。
Odalrick

@PeterPompeii希望有关缓存的附加部分可以解决您的一些问题。
奥达里克

1
@Odalrick您所描述的听起来像是数据复制。复制和缓存是两种复制数据的形式。复制是指确保副本始终拥有所有需要的数据。缓存是按需的。缓存可能会错过。缓存可用性不如缓存性能有意义。TL; DR如果您存储的东西的完整副本具有足够的一致性,则可以保证您永远不需要检查未命中,那么它就不是缓存。
布兰登

1
@Brandon复制和缓存之间的另一个区别是,当存在差异时,如何知道哪些数据是错误的。复制定义了一些有关如何合并数据的规则。另一方面,缓存始终是:缓存是错误的。
Odalrick
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.