对多租户,或不对多租户

时间:2011-04-08 14:42:00

标签: asp.net sql-server database-design fluent-nhibernate multi-tenant

我有一个困难的数据库设计决策,为我的客户基于网络的CRM的越来越多的分支机构提供多租户,我积极维护。

我很早就决定为每个分支使用单独的应用程序和单独的数据库,因为这是满足不同数据和代码要求的三个不同分支的最简单方法。我还想避免在每个查询中管理租户ID,就像我在2007年建立的遗留经典ASP( cringe )应用程序一样......恐怖。 / p>

但是现在分支机构的数据需求正在趋同,随着业务的扩展,我需要能够快速推出新的分支机构并共享全球产品SKU。

由于所有分支的表和视图都相同,现在可以使用更好的ORM工具来管理多租户应用程序,我想知道为多个分支创建共享数据库是否更好。

集中式数据库的注意事项:

  • 全球产品SKU
  • 简化的库存申请
  • 更易于备份
  • 部署一次而不是每个分支

集中式数据库的注意事项:

  • 使用单独的数据库更容易区分分支要求
  • 模块化部署(一个被击落的分支不会破坏所有)
  • 难以管理和开发共享数据库
  • 我必须重新设计发票编号(由种子生成的序列)
  • 无处不在WHERE条款
  • 恢复一个破碎的分支对其他分支有很多影响

不可能有多达10个分支机构。现在有3个。

具有该领域实际经验的开发人员,您在我的情况下会做些什么?保持应用程序& DB分离,或组合成一个巨大的系统?


编辑:关于多租户专业和缺点的好Microsoft article。我应该注意,分支之间的数据隔离不是主要问题。

8 个答案:

答案 0 :(得分:6)

如果您正在谈论10个分支机构,那么多租户似乎是一笔巨大的成本而且收益甚微。

您不提及多租户的并发症:

  • 版本控制变得困难。客户端X,Y和Z可能需要新功能,而客户端A,B和C则不需要。多租户应用程序使每个人都很难接受,特别是如果新功能需要更改数据库架构。这不是不可能的,只是更难。
  • 有些客户对他们的数据在与其他客户端相同的表格中混杂感到非常不舒服。即使我们了解得更好,但对他们来说这也是一种安全风险。法律部门讨厌它。此外,如果您为客户端转储原始数据,则需要谨慎使用共享数据库。

您可以通过更好的做法消除一些痛点:

  • 自动部署。这样可以更轻松地添加新客户端或升级/降级现有客户端。还应自动设置数据库维护(备份,重建索引)。
  • 将共享数据(SKU,库存)存储在中央数据库中,让每个应用程序实例直接或通过服务访问它。

不要误会我的意思,我工作的一个更有趣的应用程序是多租户。可以带来巨大的好处,但是你可能会看到成千上万的客户,而不是10个。

答案 1 :(得分:6)

咬紧牙关并合并它们。将租户ID添加到需要的位置,然后更改您的查询。

对于自定义,请查看允许您为特定客户端部署特定屏幕的插件类型体系结构。

我们有一种以这种方式构建的软件产品。有时它部署在客户端站点上,有时我们会托管它。对于所有意图和目的而言,与处理代码的多个分支相比,一个数量级更容易处理具有客户端特定扩展的单个代码库。

首先,当我们解决问题时,我们会为每个人解决问题。当然,如果我们打破它,我们会为每个人打破它,但这就是单元测试的目的。对于一个代码库维护一组单元测试要比为多个分支维护它们要容易得多。

我们已经做了多租户超过10年,而不是一次我回头看。一般来说,如果您在确认检索记录的人实际上是允许获取记录时已经具有安全意识,则查询并没有那么不同。

我不同意科尔宾提出的问题。应该已经通过具有基于属性的安全性结构来处理版本控制。这样您就可以通过用户或租户配置打开/关闭事物。此外,我发现很少有客户端A不希望客户端B要求的新功能。

关于数据混合的第二个问题也不是问题。只需查看salesforce.com或任何其他大型网站即可。他们绝对使用多租户架构,并根据使用它们的客户端的剪切数来判断,这似乎不是问题。这里最重要的是能够确保您的客户的数据安全。

答案 2 :(得分:3)

老实说,这是一个商业问题。您要么能够在多租户设置中为较小的用户组提供更多自定义功能,而且需要更多的IT开销。也就是说,您将需要更多的人员和硬件(管理层会阅读:资金),但会提供更大的灵活性。

如果您处于一个GIANT Borg的情况下,那么您可以降低IT开销(再次,人员和事物,管理资金),但最终用户必须减少其软件的灵活性。所有错误都是所有用户的问题,因此大的错误会很快被破坏。然而,新功能也会影响所有用户,因此它们发生得更慢。

如果你个人有能力拨打这个电话而且业务只是听你说的话,或者你可以用这样或那样的方式轻推管理我建议问你自己一系列关于你喜欢哪种情况的问题:

A)你想让更多的人管理这个并分担薪水/责任吗? B)据您所知,很快就会有第四个用户组? C)你想在这家公司待多久?

如果你对前两个回答是,那么你可能想要多租户。

答案 3 :(得分:2)

我的工作是出于监管/法律原因,我们必须将每个客户的数据保存在一个单独的数据库中。但是,必须共享某些信息,这些信息主要与查找表有关,客户端的URL对应于哪个数据库。此外,如果客户希望以某种逻辑方式分离其数据,则可以选择拥有多个数据库。因此,对于我们的每个产品,我们确实有三种类型的数据库:

  1. ApplicationData,它只有几个表,其中包含有关客户端本身的信息,例如当某个URL到达时要使用的MasterData数据库(见下文)以及该客户端可以使用哪些功能。每个产品只有一个ApplicationData,无论有多少客户使用该产品。
  2. MasterData,包含特定于客户端的信息,例如用户,角色和权限(在我们的示例中,aspnet_regsql创建的表在此处)。在此处指定的权限中,给定用户可以使用哪些ClientData数据库(参见下文)。所有MasterData数据库(对于同一产品)的架构都是相同的。
  3. ClientData,包含用户与之交互的数据。在一个产品中,这是客户可以根据大量标准进行搜索的数据,创建报告等。在另一个产品中,这包含客户端可以上传的动态数据,以便其他用户可以联系人员进行调查通过电话等。同一产品的所有ClientData数据库的架构都是相同的。
  4. 现在,有一点需要注意:对于MasterData和ClientData,我们实际上使用相同的模式,并且通常使用相同的实际数据库。这是出于历史原因,因为允许客户端具有与多个ClientData数据库相对应的一个认证数据库(MasterData)的能力是相对较新的特征,其仅适用于我们的一个产品。此外,此结构简化了部署,因为大多数客户端仅使用一个ClientData数据库。但是,MasterData和ClientData在我们的项目中的Entity Framework下有单独的实体模型,我们必须确保MasterData和ClientData之间没有直接关系,例如外键。

    此设置对我们非常有用。一个主要优点是将不同的ClientData数据库放在不同的服务器上没有问题。这有助于极大地实现负载平衡,并且它提供了一种自然的分区数据方式。如果客户愿意为其付费,我们基本上可以为客户提供大量数据和专用数据库服务器。

    在这种情况下真正帮助我们的另一件事是Red Gate的工具,特别是多脚本,SQL源代码控制和架构比较等工具。当我们升级某些东西,并且架构发生变化时,我们必须将更改部署到所有相关数据库。这些工具可以节省更多的时间。请注意,除了满意的用户之外,我与Red Gate没有任何关系。

    修改(以回应评论)

    ApplicationData是每个产品一个数据库。我们使用相同的ApplicationData模式的三个基于Web的产品,因为它们记录了基本相同类型的信息。但是,没有理由 保持这种状态。 ApplicationData数据库都在同一台服务器上。 ApplicationData中的一个表指向客户端MasterData的正确服务器和数据库名称,因此给定客户端的MasterData可以驻留在任何服务器上。

    MasterData具有每个ClientData数据库的服务器和数据库名称信息,因此数据库也可以驻留在任何服务器上。实际上,目前我们这些产品总共只有两个生产数据库服务器。 MasterData架构与每个产品类似,但我不认为它们完全相同(我必须检查)。每个客户端都有自己的MasterData。如果客户购买多个产品,则该客户的每个产品都有一个MasterData;如果客户购买了该功能(或请求自定义开发此功能),产品将以其他方式(通过Web服务进行交互)。给定产品的ClientData始终具有相同的架构。

    所以,总结一下:

    1. ApplicationData是每个产品,并且恰好在每个产品中都有相同的架构。
    2. MasterData是产品的每个客户。
    3. 产品中的客户端有一个或多个ClientData实例。
    4. 我稍微过度简化了一点,因为我们的产品中只有一个支持每个客户端多个ClientData实例。对于第二个产品,最终可能会实施。对于第三种产品,它根本就没有任何意义,并且很可能保持不变。

      我希望能回答你的问题!

答案 4 :(得分:1)

好吧,如果倾向于在不同分支机构之间共享信息和数据,那么最好有一个中央数据库。

否则,为了实现共享数据的能力,你必须经历的箍将比共享数据库所需的额外WHERE条款更糟糕。

当然,您可以将每个分支的数据库和一个额外的数据库(截至目前的第四个数据库)作为需要共享的信息的集中存储。虽然你必须看看过度复杂是否使这两个世界解决方案中的最佳或最差:)

答案 5 :(得分:1)

如果我们谈论CRM,那么一个客户在多个数据库中的可能性是多少?如果您被要求在分支机构中合并客户详细信息,那么我肯定会选择一个集中式数据库。

答案 6 :(得分:0)

IMO权力下放正在成为可维护和可扩展设计的租户。我使用的唯一集中式数据库是用于身份验证的安全性,我目前正在将其扩展为分散的数据库以进行授权。因此,所有授权都可以保持与应用程序实际位置相同的边缘而不进行网络遍历,因为授权不是缓存的理想选择。

读到你对同一个应用程序的多个分支特别感兴趣而不是真正完全不同的应用程序,听起来一个很好的选择是围绕一个种子进程构建你的数据库(实体框架支持这个),这将允许你将新的分支代码部署到ASP.NET,然后在初始构建数据库期间,物理创建表,轮询“祝福”服务器并将所有需要的数据转储到边缘服务器。

在此之后,如果要将新产品添加到主数据存储中,那么您需要进行一些复制设置,并且这些产品应该用于每个边缘存储。您可以通过直接复制数据库或查看Microsoft Sync框架等工具来实现此目的。

答案 7 :(得分:0)

您今天可能认为您只会有一些客户,但几年后您可能会意识到该产品有可能销售给数百名客户。如果发生这种情况,您会后悔使用单租户方法。

比较以下成本:

  1. 将生产系统从单租户转换为多租户,其中数据库使用客户数据填充
  2. 尽管认为您不需要这些好处,但仍在开发多租户系统
  3. 转换生产系统是一项艰巨而且非常昂贵的任务。 使用第二种方法最初可能会花费您更多,但它确实为您提供了一个非常有价值的选择,以便能够以低成本在未来添加更多客户。该选项的价格可能值得付出。