2

我们目前有一个单租户数据库架构,MySQL 运行超过 100 个数据库。我们使用 Apartment gem 在子域上切换数据库连接,一切都很好!

但是,我们现在需要创建所谓的“伞式”客户端,它可以访问我们现有客户端组的所有数据。我不认为这对于我们的单租户数据库架构来说是立即可行的(我研究了它并查询多个 MySQL 数据库似乎很糟糕),所以我开始研究 Postgres 模式的不同实现。

我正在寻找一些建议:

  • 是否可以在 Postgres 中查询多个模式并以某种方式整理结果(寻找 Rails 实现)?我可以预见主键冲突的问题吗?

  • 拥有一个以某种方式表示/复制需要访问的模式组中的所有数据的新模式会更好吗?它需要是实时的。

  • 如果是这样,在我当前使用 MySQL 的多数据库设置中可以实现类似的效果吗?(尽量减少痛苦)

我对使用数据库字段在 MySQL 中实现多租户持谨慎态度,因为数据安全/隐私对于这个产品来说是一件大事,而且这种方式很有可能导致开发人员出错。

4

4 回答 4

2

尽管在我第一次开始做 Rails 应用程序时发现了很多多租户的例子,但我也找不到一个让我感觉完全舒服的例子。但我终于有了一个令我满意的解决方案。

我从“带范围的多租户”railscast 开始

http://railscasts.com/episodes/388-multitenancy-with-scopes

然后查看使用本指南使多租户与设计子域一起工作:

https://github.com/plataformatec/devise/wiki/How-To:--Isolate-users-to-log-into-a-single-subdomain

但我并没有从表面上看。我深入了解设计是如何以这种方式工作的。

一切就绪后,我就可以使用多租户 gem:

https://github.com/wireframe/multitenant

但我并没有就此止步。多租户 gem 要求您在想要适当范围内的事物时说 Multitenant.with_tenant,所以我创建了一个看起来像这样的 TenantController:

  around_filter :scope_current_tenant

  def scope_current_tenant
    begin
      Firm.current = Firm.find_by_subdomain!(request.subdomain)
    rescue
      raise ActionController::RoutingError.new('Not Found')
    end

    Multitenant.with_tenant Firm.current do
      yield
    end

    ensure
      Firm.current = nil
    end
  end

然后我希望租户范围内的任何控制器都继承自 TenantController 而不是 ApplicationController。这样我就不必记住控制器细节中的任何内容,它“正常工作”。开发人员唯一需要考虑的是“这是处理租户数据的控制器吗?”

虽然这仍然取决于开发人员正确地做一些事情(从正确的控制器继承,在模型中说“acts_as_multitenant”,但它在实践中非常有效。

于 2013-06-24T20:56:41.590 回答
1

只是从高层次上思考这个问题。

您可以创建一个 pg视图表来访问这些数据(尽管它比访问数据库本身要慢)

然后,您希望表中有足够的唯一字段来创建复合键或复合键。(那么您不必创建新的键列,只需创建一个索引)。因为 Rails 3 与 ORM 无关,所以您可以使用 DataMapper(或者可能是新的 ROM gem)来为这个模型建立连接。

如果您使用复合键,请意识到您可能必须在模型中显式定义 *to_param* 方法才能将键构建为字符串。这是为了在您将 :id 发送到 url 时对其进行解包。

您可以通过不同的 Postgres 用户设置对该视图的访问,然后使用 Rails 的多个连接功能为其创建模型。我们之前这样做是为了聚合来自多个表的数据,但对显示的内容有一些限制,但我不明白为什么这不适用于您的用例。

另一种选择是,也许您可​​以使用 Mongo 作为“瞬态查询数据库”。BSON 会自动为您提供唯一的密钥。您可以创建本质上是 SQL 标量对象的对象。虽然不确定在这种情况下您是否想要回写原始数据库......但您可以做到这一点。

底线 IMO 是我认为最好的解决方案在于房屋的数据库方面,因为您正在使用多个数据库。在数据库层处理这些项目似乎是最好的解决方案。

说了这么多……这似乎也是一种工艺气味。如果我正确地阅读了问题,我认为您在这种情况下真正想要做的是Hadoop的设计目的......本质上是相关数据的映射/减少(又名大数据分析)

祝你好运!

于 2013-06-25T00:05:21.810 回答
1

OBS:我不是 Ruby 人,所以我只能给你 PG 方面的想法。

使用 PostgreSQL 模式,您可以轻松管理它。只需为您拥有的每个租户创建一个架构,因此在您的应用程序中,当您需要更改租户时,您只需执行以下操作:

SET search_path TO client1;

这样,当您查询表时,假设customer您只需要在同一个连接上执行:

SELECT ... FROM customer ...;

而且,当您需要查询另一个租户(不在search_path)时,您可以使用架构查询表:

SELECT ... FROM client2.customer ...;

您可以使用另一个架构来存储公共信息,例如public架构,只需将其添加到末尾search_path

SET search_path TO client1, public;
于 2013-06-24T17:32:28.590 回答
-3

不想这么说,因为听起来您已经对当前系统投入了大量资金,但这听起来像是一份更适合 NoSQL 解决方案的工作。

具体来说,我正在考虑使用“无模式”键值数据库设计的 MongoDB。这将使您能够根据密钥从数据库中提取数据并在软件中对其进行排序。MongoDB 还支持分片,让您可以在任意数量的数据库服务器上使用一个数据库,听起来它可以在您的应用程序中很好地工作。http://www.mongodb.org/上的文档可能值得检查。我不确定它是否完美契合,但听起来它可能适用于您的应用程序。

于 2013-06-24T16:14:16.990 回答