基于客户端的网站的最佳数据库策略(Ruby on Rails)

问题描述 投票:0回答:3

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

我发现这些网站的唯一区别是数据库、CSS 文件和用于个别客户图形设计的一小组图像。

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

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

似乎有两种处理数据库的方式:

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

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

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

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

如果有人对解决这个问题的最佳方法有知情的意见,我非常想听听。提前非常感谢...

--约翰

ruby-on-rails ruby database activerecord
3个回答
4
投票

我决定采用多数据库方法。这对我来说是最简单的路径,因为我不必重新设计整个应用程序。

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

before_filter :client_db         # switch to client's db

然后,在

application_controller.rb
中,我将添加如下内容:

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

然后,像

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

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

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


2
投票

使用单独的数据库(包括您已经列出的数据库)有很多优点:

  • 当您有数百万个大型文本 blob 需要搜索时,全文搜索将变得很慢(取决于服务器的功能)。
  • 分离数据库将使每个客户端的表索引速度更快。特别是,如果您接受一个新的大客户,可能会令一些早期采用的客户感到不安。突然之间,他们的应用程序将因为(对他们)没有明显原因而受到影响。再次强调,如果您的硬件容量不超过您的硬件容量,这可能不是问题。
  • 如果您删除了某个客户端,那么打包其数据库比通过 client_id 删除所有关联行要干净一些。如果他们以后改变主意,也同样可以干净地恢复它们。
  • 如果任何客户要求他们愿意付费的附加功能,您可以分叉他们的数据库结构,而无需修改其他任何人的。
  • 对于悲观主义者来说:您意外破坏所有客户端数据而不是仅破坏一个客户端数据的可能性较小。 ;)

综上所述,单一数据库解决方案可能更好:

  • 您的数据库服务器的功能使大型单个表不再是问题。
  • 保证您客户的数据库保持相同。
  • 您不必担心是否能够将每个人的数据分开以便存档/恢复或发生灾难时。

1
投票

我会选择使用客户端 ID 的单个数据库 - 您应该能够通过使用某种形式的基本模型以及将任何操作范围限制到该客户端 ID 的命名范围来减轻重构的痛苦。

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

© www.soinside.com 2019 - 2024. All rights reserved.