【问题标题】:Microservices and database joins微服务和数据库连接
【发布时间】:2015-06-28 00:05:55
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 好问题,我遇到了同样的问题,我最终获得了物化视图并对此进行了连接。我不喜欢它,但我想这对微服务来说将是一个挑战。没有正确的方法可以做到这一点,它只是一种设计选择。我知道很多人说我们可以有一个具体化的视图,但是汇总的响应成为一个问题。如果您发现更好的东西,请告诉我。
  • 我知道这是旧的,但是,这是 graphql 解决的问题吗?我也在研究这个进行分段迁移,似乎 graphql 是使这个无缝的方法。
  • 在某些时候,你应该意识到教条主义不是要走的路。 GraphQL 是在数据源之外进行聚合的一个不错的例子,它通常工作得很好。

标签: database integration microservices


【解决方案1】:
  • 当性能或延迟不太重要时(是的,我们不 总是需要它们)只使用简单的 RESTful API 就可以了 用于查询您需要的其他数据。如果你需要做多个 调用不同的微服务并返回一个您可以使用的结果 API Gateway 模式。

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

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

【讨论】:

  • 所有的好建议,但我仍然觉得很难合理化,可能是因为我们习惯于在数据库中进行大量处理。我们当前的应用程序具有复杂的存储过程,这些过程会处理大量数据,然后返回一个小的结果集。在微服务架构中,我认为这些实体应该被分成不同的有界上下文。我们知道当前的方法很丑陋,但很难证明将所有数据带回应用层进行处理。也许更多的非规范化或预先计算聚合视图会有所帮助。
  • 是的,我明白了。微服务方法并不适合所有人,您应该谨慎应用它。也许您可以从较小的更改开始。
  • 可能程序员 StackExchange 会是一个更好的地方来问这个问题:programmers.stackexchange.com/questions/279409/… 和其他标记为微服务的问题 programmers.stackexchange.com/questions/tagged/microservices
【解决方案2】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2021-07-02
          • 1970-01-01
          • 1970-01-01
          • 2017-04-22
          • 2014-03-23
          • 2019-02-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多