如何使ActiveRecord与旧的分区/分片数据库/表一起使用?

时间:2009-11-02 07:10:08

标签: ruby-on-rails activerecord legacy database-partitioning

首先感谢你的时间......在google,github和这里搜索完所有的搜索后,对于大字(分区/分片/ fedorate)更加困惑,我想我必须描述我遇到的具体问题并四处询问。

我公司的数据库处理大量用户和订单,因此我们以各种方式拆分数据库和表格,其中一些如下所述:

way             database and table name      shard by (maybe it's should be called partitioned by?)
YZ.X            db_YZ.tb_X                   order serial number last three digits
YYYYMMDD.       db_YYYYMMDD.tb               date
YYYYMM.DD       db_YYYYMM.tb_ DD             date too

基本概念是数据库和表根据字段(不一定是主键)分离,并且有太多的数据库和太多的表,因此为每个数据库编写或神奇地生成一个database.yml配置并且每个表的一个模型是不可能的,或者至少不是最佳解决方案。

我查看了drnic的魔术解决方案,datafabric,甚至是活动记录的源代码,也许我可以使用ERB生成database.yml并在filter周围做数据库连接,也许我可以使用named_scope来动态决定用于查找的表名,但更新/创建操作受限于“self.class.quoted_table_name”,因此我无法轻易解决问题。甚至我可以为每个表生成一个模型,因为它的数量最多为30个。

但这不是干!

我需要的是一个干净的解决方案,如下面的DSL:

class Order < ActiveRecord::Base
   shard_by :order_serialno do |key|
      [get_db_config_by(key), #because some or all of the databaes might share the same machine in a regular way or can be configed by a hash of regex, and it can also be a const
       get_db_name_by(key), 
       get_tb_name_by(key),        
      ]
   end
end

有人能让我高兴吗?任何帮助将不胜感激~~~~

3 个答案:

答案 0 :(得分:1)

如果您想要特定的DSL,或者与遗留分片背后的逻辑相匹配的东西,您将需要深入了解ActiveRecord并编写一个gem来为您提供这种能力。您提到的所有现有解决方案都不一定是根据您的情况编写的。您可以根据自己的意愿改变任意数量的解决方案,但最终您可能需要编写自定义代码才能获得所需内容。

答案 1 :(得分:1)

听起来,在这种情况下,您应该考虑不使用SQL。

如果数据集很大并且可以表示为键/值对(稍微去标准化),则应该查看couchDB或其他noSQL解决方案。 这些解决方案快速,完全可扩展,并且基于REST,因此可以轻松扩展,备份和复制。

我们都用相同的工具解决了所有问题(相信我,我也尝试过)。

切换到noSQL解决方案然后重写activeRecord会更容易。

答案 2 :(得分:1)

案例二(只有数据库名称更改)很容易使用DbCharmer实现。您需要在DbCharmer中创建own sharding method,它将根据密钥返回连接参数哈希值。

其他两种情况不会立即得到支持,但可以轻松添加到您的系统中:

  1. 您实现了分片方法,该方法知道如何处理分片数据库中的数据库名称,这样您就可以对模型进行shard_for(key)调用以切换数据库连接。

    < / LI>
  2. 您可以添加如下方法:

    class MyModel < ActiveRecord::Base
      db_magic :sharded => { :sharded_connection => :my_sharding_method }
    
      def switch_shard(key)
        set_table_name(table_for_key(key))  # switch table
        shard_for(key)                      # switch connection
      end
    end
    
  3. 现在您可以像这样使用您的模型:

    MyModel.switch_shard(key).first
    MyModel.switch_shard(key).count
    

    并且,考虑到您从shard_for(key)方法返回了switch_shard个调用结果,您可以像这样使用它:

    m = MyModel.switch_shard(key) # Switch connection and get a connection proxy
    m.first                       # Call any AR methods on the proxy
    m.count