每个租户具有微服务和数据库的 SAAS 应用程序

SAAS application with microservices and database per tenant

我正在为多租户 SAAS 模型设计 Web 应用程序,由于一些规定,我们决定每个租户都有一个数据库,并且我们正在考虑为我们的中间件提供微服务。但是我有点困惑,微服务架构谈论 'every microservice has their own database'。所以这是我的问题

  1. 如果我为微服务使用共享数据库,它违反了 concept/purpose 微服务设计,在这种设计中,它们都应该被隔离,任何更改都应该仅限于该微服务。

我可以想到一个模仿我的数据库表的层作为 DTO,每个微服务都通过这个层与数据库通信,如果我在这里错了请纠正我。

  1. 如果我使用每个微服务都有自己的数据库,那么每个租户都有一个数据库几乎是不可能的,否则每个微服务最终都会有 n 个数据库。

那么,对于每个租户一个数据库来设计我们的中间件的正确方法应该是什么? 或者谁有更好的方法欢迎分享。

下面是我们开始的高级设计 here

我们的应用程序是 SaaS 和具有微服务架构的多租户。我们确实为每个服务使用 1 个数据库,但在某些情况下,它实际上只是每个租户一个单独的模式,而不是一个单独的实例。

"database per service" 中的关键概念都是关于避免在服务之间共享 tables/documents,而与具体实现方式无关。如果两个服务都访问同一个 table,这将成为服务之间的紧密耦合点以及常见的故障点 - 微服务旨在避免这两件事。

Database-per-service means don't share persistence between multiple services, how you implement that is up to you.

多租户是另一个挑战,有多种方法可以解决它。在我们的案例中(法规没有规定我们的架构),我们设计了我们的租户感知 table-结构,其中 TenantId 作为主键的一部分。每个租户感知服务都实现了这种分离,我们的授权服务有助于将用户保持在其指定租户的边界内。

如果您需要比 key/value 分离更多的分离,我希望利用模式作为一个很好的工具来隔离数据和安全性:

  • 每个微服务可以有一个数据库实例(比如 SQL 服务器实例),并且在每个实例中每个租户都有一个模式。
  • 一开始这可能有点矫枉过正,我认为您可以安全地为每个 service/tenant 组合创建一个架构,直到该数字成为一个问题。

在任何一种情况下,您都可能希望在您选择的数据库中编写一些工具来帮助管理您不断增长的模式集合,但除非您最终要拥有成千上万的租户,否则这应该会让您很漂亮远在路上。

最后一点是,您将严重依赖某种集成总线来保持多个独立数据存储的同步。我强烈建议您在设计上花费尽可能多的时间,因为这些事件将成为系统的生命线。例如,在我们的多租户设置中,创建一个新租户涉及我们 80% 的其他服务(通过广播消息),以便这些服务准备好与新租户交互。有些集成事件需要快速发生,有些则需要时间,但管理所有这些活动部件是一项挑战。

你应该在这里区分两件事:

  1. 数据库分片 分片是一种与水平分区相关的数据库架构模式,在这种模式中,您可以根据一些逻辑键拆分数据库。在您的情况下,您的逻辑键是您的租户(tenantId 或 tenantCode)。分片将允许您将数据从一个数据库拆分到多个物理数据库。理想情况下,您可以为每个逻辑分片键创建一个数据库。在您的情况下,这意味着您可以为每个租户拥有最好的数据库。请记住,您不必将它拆分得那么远。如果您的数据不够大,不值得将每个租户数据都放在单独的数据库中,请从 2 个数据库开始,将一半的租户放在 1 个物理数据库中,一半放在第二个物理数据库中。然后,您可以通过在数据库中保存某些配置或另一个 table 哪个租户在哪个数据库中来在您的应用程序层上进行协调。随着数据的增长,您可以迁移 and/or 创建额外的物理数据库或物理分片。

  2. 每个微服务的数据库 每个微服务都有自己的数据库是微服务架构的基本规则之一。有多种原因,其中一些是:

    • 缩放
    • 隔离
    • 针对不同的微服务使用不同的数据库技术(如果需要)
    • 开发团队分离

您可以阅读更多相关信息 here。当然它有一些缺点,但请记住这是微服务架构中的关键规则之一。

您的问题

If I use shared database for microservices, it violate concept/purpose of microservices design where they all should be isolated and any change should limited to that microservice.

如果可以尽量避免多个微服务共享数据库。如果你最终这样做,你应该考虑你的架构设计。有时强制使用一个数据库表明某些微服务应该合并到一个数据库中,因为它们之间的耦合太大,因此使用它们的开销变得非常复杂。

If I use every microservice has their own database then its almost impossible to have one database per tenant, otherwise each microservice end-up with n number of database.

我真的不同意这是不可能的。是的,这很难管理,但如果您决定使用微服务并且需要数据库分片,那么您需要处理额外的复杂性。当然,每个微服务有一个数据库,然后每个微服务有 n 个数据库,这可能非常具有挑战性。 作为解决方案,我建议如下:

  • 将租户(tenantId 或 tenantCode)作为数据库中每个 table 的列。这样,如果您决定需要对模式中的 table、一组 table 或属于某个微服务的整个数据库进行分片,您将能够在以后轻松迁移。正如上面关于数据库分片的部分所说,您可以从一个物理分片(一个物理数据库)开始,但已经定义了您的逻辑分片(在这种情况下使用每个 table 中的租户信息)。

  • 仅在您需要的微服务中将数据物理分离到不同的分片。假设您有 2 个微服务:产品库存微服务和客户微服务。假设您的产品库存微服务数据库中有 3 亿种产品,而只有 50 万客户。您不需要在客户微服务中为每个租户建立一个数据库,但在具有 3 亿条记录的产品库存微服务中,这将非常有助于提高性能。 正如我上面所说,从 1 或 2 个物理数据库开始,随着时间的推移,您的数据会增加并且您需要它。通过这种方式,您至少可以在不需要的时候节省一些服务器开发和维护开销。