MongoDB中面向多租户数据库的推荐方法是什么?

122

我正在考虑使用MongoDB创建一个多租户应用程序。我目前不清楚需要承载多少租户,但我希望能够扩展到数千个。

我可以想到三种策略:

  1. 所有租户在同一个集合中,使用租户特定的字段进行安全管理
  2. 在单个共享数据库中为每个租户创建1个集合
  3. 为每个租户创建1个数据库

我的想法是选择第2种选项。

有什么想法和影响吗?


3
为了我的应用程序,我最终选择了Postgresql(通过hstore扩展,我们获得了关系型数据库和一些类似于NoSQL的功能),而不是MongoDB,并在Rails中使用作用域处理多租户。我们使用的是与这个Railscast中所使用的类似方法:http://railscasts.com/episodes/388-multitenancy-with-scopes - Braintapper
2
我知道这个问题已经有了一个答案,但其他人应该参考mongohq网站上的官方文档:http://support.mongohq.com/use-cases/multi-tenant.html。它明确反对下面@Braintapper的解决方案。 - user437329
1
答案已更新。你链接中的信息在2010年5月并不容易获得。 - Braintapper
@medBo 是的,我们正在使用我们自己定制的Postgresql解决方案。您可以拥有任意数量的租户,只需要确保您的数据库设计符合您的要求即可。在安全方面,您需要做一些工作。有一些预设的宝石和库可以帮助管理。 - Braintapper
@Braintapper 感谢您的回复,我正在考虑PostgreSQL的架构分离,但似乎它有其限制,也许做“作用域解决方案”更好,您能给我一个关于安全问题需要做哪些工作的想法吗? - medBouzid
显示剩余3条评论
6个回答

88

我面临着同样的问题,并正在考虑不同的选择。因为我有多年创建SaaS多租户应用程序的经验,所以我也打算基于自己在关系型数据库方面的经验选择第二个选项。

在做研究时,我发现了mongodb支持站点上的这篇文章(很久以前添加的,已经不存在): https://web.archive.org/web/20140812091703/http://support.mongohq.com/use-cases/multi-tenant.html

这些人指出要不惜一切代价避免第二种选项,我理解这并非特别适用于mongodb。我的印象是,这适用于我研究的大多数NoSQL数据库(CoachDB、Cassandra、CouchBase Server等),原因是由于数据库设计的特定性。

集合(或桶或者不同DB中称之为什么)不同于RDBMS中的安全模式,尽管它们像文档的容器一样的表现,但对于应用良好的租户分离来说是无用的。我找不到能够基于集合应用安全限制的NoSQL数据库。

当然,你可以使用mongodb基于角色的安全性在数据库/服务器级别上限制访问。(http://docs.mongodb.org/manual/core/authorization/

我建议在以下情况下选择第一种选项:

  • 你有足够的时间和资源来处理设计、实现和测试该场景的复杂性。
  • 如果你不会在不同租户的数据库中有太多的结构和功能上的差异。
  • 你的应用程序设计将允许租户在运行时进行最小的自定义。
  • 如果你想优化空间并最小化硬件资源的使用。
  • 如果你将有数千个租户。
  • 如果你想快速扩展且成本低廉。
  • 如果你不会基于租户备份数据(为每个租户保留单独的备份)。即使在这种情况下也可以这样做,但需要付出巨大的努力。

如果符合以下条件,我会选择变体3:

  • 您只有少量租户(几百个)。
  • 业务需求需要支持不同租户之间的数据库结构大幅度差异(例如与第三方系统集成、数据导入/导出等)。
  • 您的应用程序设计将允许客户(租户)在应用程序运行时进行重大更改(添加模块、自定义字段等)。
  • 您有足够的资源快速扩展新的硬件节点。
  • 您被要求为每个租户保留版本/备份数据。此外,还要轻松恢复数据。
  • 法律/监管限制强制您将不同的租户保存在不同的数据库中(甚至是数据中心)。
  • 如果想要充分利用mongodb的开箱即用的安全功能,如角色。
  • 租户之间的大小存在明显差异(您有很多小租户和很少的大租户)。

如果您提供有关应用程序的其他详细信息,我可以给您更详细的建议。


11
我猜原始链接已经失效了,所以使用存档链接:https://web.archive.org/web/20140812091703/http://support.mongohq.com/use-cases/multi-tenant.html - Peter Butkovic
你好,我们如何使用MongoDB在当前数据库中创建新的数据库? - HEMAL
@Russian 如果我们选择方案1,我们将如何处理索引? - Robins Gupta

10

我在这个链接的评论中找到了一个好的答案:

http://blog.boxedice.com/2010/02/28/notes-from-a-production-mongodb-deployment/

基本上,选项#2似乎是最好的选择。

引用David Mytton的评论:

我们决定不为每个客户创建一个数据库,因为MongoDB分配其数据文件的方式。每个数据库使用自己的一组文件:

数据库的第一个文件是dbname.0,然后是dbname.1等。dbname.0将是64MB,dbname.1是128MB,以此类推,直到2GB。一旦文件达到2GB大小,每个后续文件也是2GB。

因此,如果最后一个数据文件的大小为1GB,则该文件可能有90%的空余空间,即使它最近被使用过。

来自手册。

随着用户注册试用并尝试使用我们的产品,我们将获得越来越多至少为2GB的数据库,即使整个数据文件没有被完全使用。相比于每个客户都有几个数据库,磁盘空间可以最大限度地利用,我们发现这样使用了大量的磁盘空间。

分片将按照集合为标准进行,这在集合从未达到最小分片大小的情况下(例如仅存储用户登录详细信息的集合)会出现问题。但是,我们已经要求也可以按照每个数据库的级别进行操作。请参见

http://jira.mongodb.org/browse/SHARDING-41

使用大量的集合不会影响性能。参见http://www.mongodb.org/display/DOCS/Using+a+Large+Number+of+Collections


2
正如其他答案所建议的那样,#2 不是一个好的方法。请考虑更改接受的答案,因为这可能会误导其他开发人员。 - clopez
1
由于自2010年该问题首次提出以来情况发生了重大变化,因此更改了接受的答案。 - Braintapper

3

这里有一篇关于多租户数据架构的MSDN上的合理文章,你可能会想要参考。这篇文章涉及到的一些关键主题:

  • 经济考虑
  • 安全性
  • 租户考虑
  • 监管(法律)
  • 技能集担忧

此外,文章还涉及了一些软件即服务(SaaS)配置模式。

另外,值得一看的是来自SQL Anywhere团队的有趣写作

我的个人看法 - 除非你确定有强制的安全/信任,否则我会选择选项3,或者如果可扩展性问题阻止回退到至少选项2。话虽如此...我对使用共享“模式”感到非常紧张,但我会乐意听取更有经验的从业者的建议。


我熟悉那篇MSDN文章,因为我的原始计划是使用关系型数据库。然而,我的数据相当不结构化,这让我开始调查像MongoDB这样的NoSQL数据库。似乎MongoDB没有像Lotus Domino那样的ACL支持,我也不想重复造轮子,这让我认为2或3是正确的选择。此外,我也不知道在MongoDB中可能会遇到多少集合或数据库的限制。 - Braintapper

3

我会选择第二个选项。

不过你也可以设置mongod.exe的命令行选项——--smallfiles。这意味着extent(MongoDB数据存储的最小单位)的最大文件大小为0.5GB而不是2GB。我已经在mongo 1.42上进行了测试,所以第三个选项并非不可能。


只是为了帮助,回顾一下:[http://yazezo.com/2013/10/how-to-setup-saas-cloud-multi-tenant.html](http://yazezo.com/2013/10/how-to-setup-saas-cloud-multi-tenant.html) - KMån

0
根据我的研究MongoDB. Trucos y consejos. Aplicaciones multitenant.,如果您不知道可以有多少租户,则不建议使用该选项,因为当涉及到分片时会变得复杂,而且想象一下在单个数据库中拥有数千个集合...所以在您的情况下,建议使用选项一。现在,如果您将拥有有限数量的用户,则情况就不同了,是的,您可以像您想的那样使用选项二。

-4

虽然这里讨论的是NoSQL和主要的MongoDB,但我们在Citus使用PostgreSQL构建分布式/分片的多租户数据库。

我们的用例指南通过一个示例应用程序,涵盖了模式和各种多租户特定功能。

对于更不规则的数据,我们使用PostgreSQL的JSONB列来存储此类和特定于租户的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接