【问题标题】:Multi-tenant rails application: what are the pros and cons of different techniques?多租户 Rails 应用:不同技术的优缺点是什么?
【发布时间】:2011-10-23 14:23:50
【问题描述】:

我最初为一个客户编写了我的 Ruby on Rails 应用程序。现在,我正在更改它,以便它可以用于不同的客户。我的最终目标是某些用户(不是我)可以单击一个按钮并创建一个新项目。然后生成所有必要的更改(新模式、新表、代码处理),而无需我编辑 database.yml 文件或添加新模式定义。我目前正在使用 SCOPED 访问权限。所以我有一个项目模型,其他关联模型有一个 project_id 列。

我查看了有关 Rails 中的多租户应用程序的其他帖子。很多人似乎建议在 Postgres 中为每个新客户端创建不同的模式。然而,对我来说,新客户在数据模型方面拥有不同的模式并没有多大用处。每个客户端将拥有相同的表、行、列等。

我对每个客户的愿景是,我的生产数据库首先有一个包含不同项目/客户的表。这些表中的每一个都链接到一组表,这些表几乎相同,但数据不同。换句话说,一张桌子。或者换句话说,第一个表将映射到具有相同结构的每个客户端的不同数据集。

我解释我的愿景的方式是否与 Postgres 实现不同“模式”的方式完全相似?它看起来像嵌套表吗?还是 Postgres 必须查询数据库中的所有信息?我目前不使用 Postgres,但我愿意学习它是否适合设计。如果您知道适合我需要的与 Rails 配合使用的数据库软件,请告诉我。

现在,我正在使用作用域来完成多租户应用程序,但感觉它不是可扩展的或干净的。但是,如果我向他们提供可填写的信息,它确实使非技术用户可以很容易地创建一个新项目。您知道多模式 Postgres 定义是否可以在用户单击按钮后自动运行?如果可能的话,我希望这由 Rails 处理,而不是由外部脚本处理? (请务必建议)

最重要的是,您是否推荐任何插件或者我应该为此任务采用不同的框架?我发现 Rails 在上述某些抽象情况下受到限制,这是我第一次遇到 Rails 扩展问题。

欢迎任何与多租户应用程序或我的情况相关的建议。也欢迎任何需要澄清或额外建议的问题。

谢谢, --戴夫

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 database-design postgresql multi-tenant


    【解决方案1】:

    MSDN 有一个很好的introduction to multi-tenant data architecture

    在频谱的一端,每个租户拥有一个数据库(“不共享任何内容”)。 “无共享”使灾难恢复变得非常简单,并且租户之间的隔离程度最高。但它的每租户平均成本也最高,每台服务器支持的租户最少。

    另一方面,您在每个共享表(“共享所有内容”)的每一行中都存储了一个租户 ID 号。 “共享一切”使灾难恢复变得困难——对于单个租户,您只需要恢复每个共享表中的 一些 行——而且它具有最低程度的隔离。 (格式错误的查询可能会暴露私有数据。)但它的每租户成本最低,并且每台服务器支持的租户数量最多。

    我对每个客户的愿景是我的生产数据库首先有一个 不同项目/客户的表格。每一张桌子 指向一组几乎相同但不同的表的链接 数据。换句话说,一张桌子。或者换句话说,第一个 表将映射到每个客户端的不同数据集 相同的结构。

    听起来就像您在谈论每个租户一个架构。密切注意权限(SQL GRANTREVOKE 语句。和ALTER DEFAULT PRIVILEGES。)

    【讨论】:

    • 谢谢。该指南真的很有帮助。单独的模式选项对我来说真的很有吸引力。你知道这是否对rails有任何支持,或者我基本上会反对吗?
    • 如果你搜索这个页面,edgeguides.rubyonrails.org/3_0_release_notes.html,你会发现有一些架构支持。几十年来我一直在做这些事情;我倾向于对任何有记录的支持持悲观态度。 (还记得 MySQL 对外键约束的“支持”吗?它通过解析 FK 约束,然后忽略它们来支持它们。)如果我是你,我会设计一个或两个表的设计并进行测试。
    【解决方案2】:

    有两个关于多租户的 railscast 使用 scopes and subdomains 和另一个帮助处理 multiple schemas

    还有multitenant gem 可以帮助您处理范围,apartment gem 可以处理多个模式。

    这也是multitenancy-with-rails上的一个很好的介绍。

    【讨论】:

      【解决方案3】:

      不要忘记使用默认作用域,在按照您现在的工作方式创建命名作用域时,感觉它确实可以做得更好。几个月前,我遇到了 Samuel Kadolph 的 this guide 关于这个问题,看起来它可以很好地满足您的情况,并且可以让您的应用程序摆脱一些 PgSQL 独有的功能。

      基本上,他描述设置应用程序的方式涉及将租户的概念添加到您的应用程序中,然后使用它在查询时使用数据库来确定数据范围。

      【讨论】:

      • 真的很干净!这将使代码更简单。但是,您知道这会如何影响性能吗?它是否对每个租户的每个表中的数据进行分区?或者它是否按其主键存储组织并需要完整的迭代来获取特定租户的数据?
      • 租户应该是一个主键,因为它就像任何 Rails 关系一样。它与 SQL 或您使用的任何数据库中的任何其他索引主键查找一样慢。
      猜你喜欢
      • 2011-01-09
      • 2015-07-24
      • 2011-04-29
      • 2017-10-05
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多