2009-11-02 45 views
3

感謝您的時間第一......在谷歌,github和這裏搜索之後,並且對大詞(分區/分片/ fedorate)感到困惑,我認爲我必須描述我遇到的具體問題,問問周圍。如何使ActiveRecord與傳統的分區/分片數據庫/表一起工作?

我公司的數據庫中有大量的用戶和訂單交易,於是將通過各種方式的數據庫和表,一些描述如下:

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 

的基本概念是,數據庫和表分隔acording到現場(並不是主鍵),並且數據庫太多,表格太多,因此,爲每個數據庫寫入或奇蹟般地生成一個database.yml配置文件,而爲每個表格創建一個模型是不可能的,或者至少不是最佳的解決方案。我研究了drnic的魔術解決方案,datafabric,甚至是活動記錄的源代碼,也許我可以使用ERB生成database.yml,並在過濾器中執行數據庫連接,也許我可以使用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 

可有人微啓我嗎?任何幫助將不勝感激~~~~

回答

1

第二種情況(只有數據庫名稱發生更改)使用DbCharmer很容易實現。您需要在DbCharmer中創建您的own sharding method,這將返回基於密鑰的連接參數哈希。

另外兩起案件中不支持馬上,但可以很容易地添加到您的系統:

  1. 你實現,知道如何在分片dabatase處理數據庫名稱拆分方法,這將給你有能力做shard_for(key)調用你的模型來切換數據庫連接。

  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 
    
+0

感謝您的詳細解決方案,它非常有用。然而,似乎有一個致命的問題:set_table_name是一個類方法,它的影響是整個類的,我無法將其範圍限定在特定的對象。 這就是爲什麼我正在考慮更多內部的東西,比如「爲每個表奇蹟般地生成一個模型」,這似乎在您的魔法解決方案中使用(仍在努力瞭解DbCharmer的來源)。 如果可能,我想將它添加到DbCharm中,但還有另外一個致命的問題,DbCharmer沒有單元測試......那麼我怎樣才能避免在這個過程中破壞某些東西呢? – Utensil 2011-10-22 09:59:57

+0

DbCharmer支持範圍內的連接切換。您始終可以執行MyModel.on_db(:foo){...}或MyModel.switch_shard(key){...},它只會切換塊中的連接。至於測試,有一個單獨的項目與規格(幾乎100%覆蓋寶石的代碼):https://github.com/kovyrin/db-charmer-sandbox – kovyrin 2011-10-23 15:51:21

1

如果你想要那個特定的DSL,或者與遺留分片背後的邏輯相匹配的東西,你將需要挖掘到ActiveRecord並編寫一個gem來給你那種能力。您提到的所有現有解決方案都不一定是根據您的情況編寫的。您可能可以根據自己的意願彎曲任意數量的解決方案,但最終您可能必須編寫自定義代碼才能獲得您所需的內容。

+0

感謝您的回答!我確實挖掘了AR的來源,並且挖掘了我找到的不同解決方案的來源。我完成了所有這些工作,以便爲AR編寫我自己的插件。最接近的解決方案之一是sharded_database插件,儘管它不支持表分區......我猜「class << self; set_table_name; end」可能會讓我更改每個AR實例的表名。但成本,我不知道。並且每次更改數據庫連接,都會放棄池的所有好處...通過提問,我試圖尋找類似情況下的人... – Utensil 2009-11-05 09:27:28

+0

如果碰巧有一個優雅的設計,觸摸很少並侵入AR,我將不勝感激的光... – Utensil 2009-11-05 09:32:27

1

聽起來像,在這種情況下,你應該考慮不使用SQL。

如果數據集很大並且可以表示爲鍵/值對(稍微去規範化),那麼您應該查看一下couchDB或其他noSQL解決方案。 這些解決方案速度快,可完全擴展,並且基於REST,因此很容易進行增長和備份和複製。

我們都已經用相同的工具解決了所有的問題(相信我,我也嘗試了)。

切換到noSQL解決方案然後重寫activeRecord會容易得多。

+0

感謝您的答案!開放解決方案總是很棒〜CouchDB是一件好事。我*愛* erlang。不幸的是,在我的情況下,非SQL不是一種選擇。 MySQL數據庫和許多其他C/C++程序是真正的和嚴重的業務中的大多數,我只是試圖用rails來與他們交談。 – Utensil 2009-11-05 09:19:11