【问题标题】:best database strategy for a client-based website (Ruby on Rails)基于客户端的网站的最佳数据库策略(Ruby on Rails)
【发布时间】:2008-12-08 15:02:44
【问题描述】:

我已经建立了一个很好的网站系统,可以满足小众市场的需求。去年,我通过使用 Capistrano 将软件副本部署到我的 Web 服务器来销售这些网站。

在我看来,这些网站的唯一区别是数据库、CSS 文件和用于单个客户图形设计的一小部分图像。

其他一切都完全相同,或者应该是……现在我已经部署了大约 20 个这样的站点,要让它们都使用相同的代码进行更新变得很麻烦。而这个问题只会变得更糟。

我在想我应该重构这个系统,这样我就可以使用一组部署的 ruby​​ 代码,通过传入请求的 URL 动态选择正确的数据库等。

好像有两种处理数据库的方式:

  • 使用多个数据库,每个客户端一个
  • 使用一个数据库,每个表中都有一个 client_id 字段,以及一个额外的“客户端”表

目前,多数据库方法对我来说是最简单的,因为我不必重构应用程序中的每个模型来将 client_id 字段添加到所有 CRUD 操作。

但是,每次我想迁移数据库时,都必须为数十或数百个不同的数据库运行“rake db:migrate”会很麻烦。显然这可以通过脚本来完成,但它闻起来不太好。

另一方面,每个客户的“项目”表中都有 20K-50K 项目。当 items 表中有 50 万或百万个项目时,我担心全文搜索的速度。即使在 client_id 字段上有索引,我怀疑如果将项目分开到不同的客户端数据库中,搜索会更快。

如果有人对解决此问题的最佳方法有明智的意见,我非常想听听。非常感谢...

-- 约翰

【问题讨论】:

    标签: ruby-on-rails ruby database activerecord


    【解决方案1】:

    感谢伟大的 cmets。我决定采用多数据库方法。这对我来说是最简单的方法,因为我不必重新编写整个应用程序。

    我要做的是在application_controller中添加一个before_filter,所以它适用于所有的控制器......像这样:

    before_filter :client_db # 切换到客户端的数据库

    然后,在 application_controller.rb 中,我将包含如下内容:

    def client_db @client = Client.find(params[:client_id]) 规格 = Client.configurations[RAILS_ENV] new_spec = spec.clone new_spec["database"] = @client.database_name ActiveRecord::Base.establish_connection(new_spec) 结尾

    然后,像 example.com?client_id=12345 这样的 URL 将选择正确的数据库。

    由于我在 Mongrel 前面使用 Apache 作为代理,Apache 将根据客户端的网站 URL 将正确的 client_id 添加到所有请求中。因此,client_id 实际上并不是用户看到的 URL 的一部分。它只会在 Apache 和 Mongrel 之间传递。我不确定我是否正确地解释了这一点,但它确实有效并且让事情变得简洁明了。

    如果我决定将来需要使用单个数据库,那么我可以重构所有代码。目前,这似乎是最简单的方法。

    有人发现这种方法有什么问题吗?

    -- 约翰

    【讨论】:

    • 我会以不同的方式路由它,但这只是我。比如,routes.rb 中的“:user_id/:controller/:action/:id”;这样,您始终在 url 中有客户端 ID,而客户端可能会删除某些内容(例如“client =”位)。
    【解决方案2】:

    使用单独的数据库(包括您已经列出的那些)有很多好处:

    • 当您要搜索数百万个大文本 blob 时,全文搜索会变慢(取决于您的服务器的能力)。
    • 分离 DB 将使每个客户端的表索引速度更快。特别是,如果您接受一个新的大客户,它可能会让您早期采用的一些客户感到不安。突然之间,他们的应用程序将(对他们)没有明显的原因受到影响。同样,如果您保持在硬件的能力范围内,这可能不是问题。
    • 如果您删除了一个客户端,那么只打包他们的数据库要比通过 client_id 删除所有关联的行稍微干净一些。如果他们以后改变主意,同样干净地恢复它们。
    • 如果任何客户要求他们愿意支付额外的功能,您可以在不修改其他任何人的情况下分叉他们的数据库结构。
    • 对于悲观主义者:由于错误而意外破坏所有客户数据的可能性较小,而不仅仅是一个客户的数据。 ;)

    话虽如此,单数据库解决方案可能更好:

    • 您的数据库服务器的功能使大型单表成为问题。
    • 保证您客户的数据库保持不变。
    • 您不必担心为了存档/恢复或发生灾难而将每个人的数据分隔开来。

    【讨论】:

      【解决方案3】:

      我会选择使用客户端 ID 的单个数据库 - 您应该能够通过使用某种形式的基本模型和一个命名范围来减少对该客户端 ID 的任何操作,从而减少重构的痛苦。

      您可以使用诸如 Ferret 之类的索引库或类似的东西来处理全文搜索变慢的问题。一旦单个客户端的数据库变得很大,这无论如何都会成为一个问题,因此您可能需要以任何一种方式实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-16
        • 2011-08-17
        • 2021-07-06
        • 2011-11-01
        • 1970-01-01
        • 2011-01-09
        • 2011-01-20
        • 2013-04-13
        相关资源
        最近更新 更多