135

对于将单体应用程序拆分为微服务的人,您如何处理拆分数据库的难题。出于性能和简单性的原因,我从事过的典型应用程序进行了大量的数据库集成。

如果您有两个逻辑上不同的表(如果您愿意的话,是有界上下文),但您经常对大量数据进行聚合处理,那么在单体应用中,您很可能会避开面向对象,而是使用数据库的标准JOIN 功能可在将聚合视图返回到您的应用层之前处理数据库上的数据。

您如何证明将此类数据拆分为微服务的合理性,据推测您将需要通过 API 而不是在数据库中“加入”数据。

我读过 Sam Newman 的微服务书,在关于拆分 Monolith 的章节中,他举了一个“打破外键关系”的例子,他承认跨 API 进行连接会更慢 - 但他接着说,如果无论如何,您的应用程序足够快,它比以前慢有关系吗?

这似乎有点油嘴滑舌?人们的经验是什么?您使用了哪些技术来使 API 连接的性能可以接受?

4

5 回答 5

31
  • 当性能或延迟不太重要时(是的,我们并不总是需要它们),只需使用简单的 RESTful API 来查询您需要的其他数据就可以了。如果您需要对不同的微服务进行多次调用并返回一个结果,您可以使用 API Gateway模式。

  • Polyglot 持久性环境中具有冗余是非常好的。例如,您可以为您的微服务使用消息队列,并在每次更改某些内容时发送“更新”事件。其他微服务将监听所需的事件并在本地保存数据。因此,您无需查询,而是将所有必需的数据保存在特定微服务的适当存储中。

  • 另外,不要忘记缓存 :) 您可以使用RedisMemcached等工具来避免过于频繁地查询其他数据库。

于 2015-04-21T02:51:44.143 回答
12

服务可以拥有来自其他服务的某些参考数据的只读复制副本。

鉴于此,当尝试将单体数据库重构为微服务(而不是重写)时,我会

  • 为服务创建数据库架构
  • 在该架构中创建版本化* 视图** 以将该架构中的数据公开给其他服务
  • 对这些只读视图进行联接

这将使您可以独立修改表数据/结构,而不会破坏其他应用程序。

除了使用视图,我还可以考虑使用触发器将数据从一个模式复制到另一个模式。

这将是朝着正确方向的渐进式进展,建立组件的接缝,并且可以在以后完成向 REST 的迁移。

*视图可以扩展。如果需要进行重大更改,请创建相同视图的 v2 并在不再需要时删除旧版本。**或表值函数或 Sprocs。

于 2015-06-17T11:18:46.170 回答
8

CQRS---Command Query Aggregation Pattern 是 Chris Richardson 的答案。让每个微服务更新自己的数据模型并生成事件,这些事件将更新物化视图,该视图具有来自早期微服务所需的连接数据。这个 MV 可以是任何 NoSql DB 或 Redis 或经过查询优化的 elasticsearch。这种技术导致最终一致性,这绝对不错,并且避免了实时应用程序端连接。希望这个答案。

于 2018-02-12T13:40:36.533 回答
3

我会将使用领域的解决方案分开,比如运营和报告。

对于为需要来自其他微服务的数据的单一表单提供数据的微服务(这是操作案例),我认为使用 API 连接是可行的方法。你不会去获取大量数据,你可以在服务中进行数据集成。

另一种情况是您需要对大量数据进行大查询以进行聚合等(报告案例)。对于这种需要,我会考虑维护一个共享数据库——类似于您的原始方案并使用您的微服务数据库中的事件对其进行更新。在这个共享数据库上,您可以继续使用您的存储过程,这将节省您的工作量并支持数据库优化。

于 2018-04-03T07:45:14.690 回答
2

在微服务中,您创建差异。阅读模型,例如:如果您有两个差异。有界上下文并且有人想要搜索这两个数据然后有人需要监听来自两个有界上下文的事件并为应用程序创建特定的视图。

在这种情况下,将需要更多空间,但不需要连接,也不需要连接。

于 2018-02-09T10:40:18.730 回答