ActiveRecord を従来のパーティション化/シャード化されたデータベース/テーブルで動作させるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/1659829

質問

まずはお時間をいただきありがとうございます...Google、github、そしてここですべての検索を行った結果、大きな言葉 (パーティション/シャード/フェドレート) についてさらに混乱してしまいました。私が遭遇した具体的な問題について説明し、周りに尋ねる必要があると思いました。

私の会社のデータベースは大量のユーザーと注文を処理するため、データベースとテーブルをさまざまな方法で分割しています。その一部を以下に説明します。

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

基本的な概念は、データベースとテーブルがフィールド (必ずしも主キーではない) に従って分離されており、データベースとテーブルが多すぎるため、各データベースと 1 つのモデルに対して 1 つの database.yml 構成を記述するか魔法で生成するというものです。テーブルごとに実行することは不可能であるか、少なくとも最適な解決策ではありません。

drnic のマジック ソリューション、datafabric、さらにはアクティブ レコードのソース コードを調べました。おそらく ERB を使用して、database.yml を生成し、フィルターの周りでデータベース接続を行うことができます。また、named_scope を使用してテーブル名を動的に決定できるかもしれません。検索しますが、更新/作成操作は「self.class.quoted_table_name」に制限されているため、問題を簡単に解決できませんでした。また、その量は最大 30 個なので、各テーブルに 1 つのモデルを生成することもできました。

しかし、これは単なるドライではありません。

私に必要なのは、次の 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

誰か教えてくれませんか?助けていただければ幸いです~~~~

役に立ちましたか?

解決

ケース 2 (データベース名のみが変更される) は、次のように実装するのが非常に簡単です。 デブチャーマー. 。を作成する必要があります 独自のシャーディング方法 DbCharmer では、キーに基づいて接続パラメータのハッシュが返されます。

他の 2 つのケースはすぐにはサポートされていませんが、システムに簡単に追加できます。

  1. シャーディングされたデータベースでデータベース名を処理する方法を認識するシャーディング メソッドを実装すると、次のことが可能になります。 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 
    

他のヒント

特定の DSL や、従来のシャーディングの背後にあるロジックに一致するものが必要な場合は、ActiveRecord を詳しく調べて、その種の機能を提供する gem を作成する必要があります。あなたが言及した既存のソリューションはすべて、必ずしもあなたの状況を念頭に置いて書かれたものではありません。希望に応じて任意の数のソリューションを変更できるかもしれませんが、最終的にはおそらく、探しているものを取得するためにカスタム コードを作成する必要があります。

この場合、SQL を使用しないことを検討する必要があるようです。

データ セットが非常に大きく、キーと値のペアとして (少し非正規化して) 表現できる場合は、couchDB またはその他の noSQL ソリューションを検討する必要があります。これらのソリューションは高速で完全にスケーラブルで、REST ベースであるため、拡張、バックアップ、複製が簡単です。

私たちは皆、同じツールを使ってすべての問題を解決することに慣れています (信じてください、私もそうしようとしています)。

activeRecord を書き直すよりも、noSQL ソリューションに切り替える方がはるかに簡単です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top