如何使用共享表结构创建多租户数据库?

时间:2010-02-06 12:02:35

标签: sql mysql database-design multi-tenant

我们的软件目前在MySQL上运行。所有租户的数据都存储在同一架构中。由于我们使用Ruby on Rails,我们可以轻松确定哪些数据属于哪个租户。然而,有些公司当然担心他们的数据可能会受到损害,所以我们正在评估其他解决方案。

到目前为止,我已经看到了三个选项:

  • 多数据库(每个租户都有自己的 - 与每个客户的服务器几乎相同)
  • 多架构(在MySQL中不可用,每个租户在共享数据库中获取自己的架构)
  • 共享架构(我们当前的方法,可能在每列上有额外的识别记录)

Multi-Schema是我最喜欢的(考虑成本)。但是,创建一个新帐户并进行迁移似乎非常痛苦,因为我必须迭代所有模式并更改其表/列/定义。

问:多架构似乎被设计为每个租户的表格略有不同 - 我不希望这样。是否有任何RDBMS允许我使用多模式多租户解决方案,其中表结构在所有租户之间共享?

P.S。通过多重我的意思是超多(10.000+租户)。

4 个答案:

答案 0 :(得分:84)

  

然而,有一些公司   当然谁担心他们的数据可能会   被妥协,所以我们正在评估   其他解决方案。

这很不幸,因为客户有时会误以为只有物理隔离可以提供足够的安全性。

有一篇有趣的MSDN文章,标题为Multi-Tenant Data Architecture,您可能需要查看。这就是作者如何解决对共享方法的误解:

  

一个常见的误解就是这样   只有物理隔离才能提供   适当的安全水平。在   事实上,使用共享存储的数据   方法还可以提供强大的数据   安全,但需要使用更多   复杂的设计模式。

关于技术和业务方面的考虑,本文简要分析了某种方法可能比另一种方法更合适的地方:

  

的数量,性质和需求   您期望服务的租户都会受到影响   您的数据架构决策   不同的方法。以下一些   问题可能会让你偏向更多   孤立的方法,而其他人可能   偏向于更加共享   方法

     
      
  • 您希望定位多少潜在租户?你可能无处可去   接近能够估计   有权使用的预期用途,但是   从数量级来考虑:   你在为它建立一个应用程序吗?   数百个租户?成千上万的?十   成千上万?更多?你越大   期待您的租户基础,   你更有可能想要考虑   一种更为共享的方法。

  •   
  • 您希望平均租户的数据占用多少存储空间?   如果你期望一些或所有租户   存储非常大量的数据,   可能是单独的数据库方法   最好。 (的确,数据存储   要求可能会迫使你采用   无论如何,单独的数据库模型。如果是这样,   设计它会容易得多   应用程序的方式   开始而不是移动到   稍后单独的数据库方法。)

  •   
  • 您希望普通租户支持多少并发最终用户?   数字越大,越多   适当的更孤立的方法   将满足最终用户的要求。

  •   
  • 您是否希望提供任何每租户增值服务,例如   作为每个租户备份和还原   能力?这样的服务更容易   通过更孤立的提供   方法

  •   

更新:进一步更新预计的租户数量。

对于大多数情况(如果不是所有情况),预期的租户数量(10k)应排除多数据库方法。我不认为你会想到维护10,000个数据库实例,每天必须创建数百个新实例。

仅从该参数看,共享数据库,单模式方法看起来最合适。事实上,您将为每个租户存储大约50Mb,并且不存在每个租户附加组件,这使得这种方法更加合适。

上面引用的MSDN文章提到了三种安全模式,它们解决了共享数据库方法的安全问题:

如果您对应用程序的数据安全措施有信心,您将能够为您的客户提供Service Level Agrement,以提供强大的数据安全保障。在您的SLA中,除了保证之外,您还可以描述为确保数据不受损害而采取的措施。

更新2:显然,微软的人员移动/撰写了一篇关于这个主题的新文章,原来的链接已经消失了,这是新的一个:Multi-tenant SaaS database tenancy patterns(感谢Shai Kerer)

答案 1 :(得分:16)

以下是Salesforce.com上有关如何实施多租户的白皮书的链接:

http://www.developerforce.com/media/ForcedotcomBookLibrary/Force.com_Multitenancy_WP_101508.pdf

他们有一个巨大的表w / 500字符串列(Value0,Value1,... Value500)。日期和数字以一种格式存储为字符串,以便它们可以在数据库级别转换为其本机类型。有一些元数据表定义了数据模型的形状,每个租户可以是唯一的。还有其他表用于索引,关系,唯一值等。

为什么麻烦?

每个租户都可以在运行时自定义自己的数据模式,而无需在数据库级别进行更改(更改表等)。这绝对是做这样的事情的艰难方法,但非常灵活。

答案 2 :(得分:15)

我的经验(尽管是SQL Server)是多数据库的方法,每个客户端都有自己的数据库。因此,尽管我没有mySQL或Ruby On Rails体验,但我希望我的输入可能会增加一些价值。

原因包括:

  1. 数据安全/灾难恢复。每个公司的数据都与其他公司完全分开存储,从而降低了数据被泄露的风险(如果您引入代码错误,这意味着在不应该的情况下错误地查看其他客户数据),最大限度地减少一个客户的潜在损失,如果一个特定的数据库被破坏等。客户感知到的安全利益甚至更大(增加额外的副作用!)
  2. 可扩展性。基本上,您要将数据分区以实现更高的可扩展性 - 例如数据库可以放在不同的磁盘上,您可以将多个数据库服务器联机,更容易移动数据库以分散负载。
  3. 性能调整。假设你有一个非常大的客户端和一个非常小的客户端。使用模式,数据量等可能会有很大差异。如果需要,您可以更轻松地调整/优化每个客户端。
  4. 我希望这确实提供了一些有用的输入!还有更多原因,但我的想法一片空白。如果它重新开始,我会更新:)

    修改
    自从我发布这个答案后,现在很明显我们正在谈论10,000多个租户。我的经验是在数百个大型数据库中 - 我不认为10,000个单独的数据库对于您的方案来说太容易管理,所以我现在不喜欢您的方案的多数据库方法。特别是现在很清楚,你正在谈论每个租户的小数据量!

    在这里保留我的答案,因为它可能对类似船上的其他人有一些用处(租户较少)

答案 3 :(得分:8)

正如您所提到的,每个租户的一个数据库是一个选项,并且与它有一些更大的权衡。它可以在较小的规模上很好地工作,例如单个数字或低10个租户,但除此之外,它变得更难管理。这两者都只是迁移,但也只是保持数据库正常运行。

每个模式模型不仅对每个模式的唯一模式有用,尽管仍然在所有租户中运行的迁移变得困难,并且在1000个模式中Postgres可能开始出现问题。

更具可扩展性的方法绝对是让租户随机分布,存储在同一个数据库中,但跨越不同的逻辑分片(或tables)。根据您的语言,有许多库可以帮助解决这个问题。如果您正在使用Rails,那么可以使用一个库来设置租约acts_as_tenant,这有助于确保您的租户查询仅撤回该数据。还有一个gem apartment - 虽然它使用模式模型,但它确实有助于跨所有模式的迁移。如果你正在使用Django那里有一个数字,但其中一个比较流行的似乎是schemas。所有这些在应用程序级别提供更多帮助。如果您直接在数据库级别寻找更多内容,Citus专注于使multi-tenancy的这种分片更加开箱即用。