ActiveRecord を従来のパーティション化/シャード化されたデータベース/テーブルで動作させるにはどうすればよいですか?
-
11-09-2019 - |
質問
まずはお時間をいただきありがとうございます...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 つのケースはすぐにはサポートされていませんが、システムに簡単に追加できます。
シャーディングされたデータベースでデータベース名を処理する方法を認識するシャーディング メソッドを実装すると、次のことが可能になります。
shard_for(key)
モデルを呼び出してデータベース接続を切り替えます。次のようなメソッドを追加します。
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
これで、モデルを次のように使用できます。
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 ソリューションに切り替える方がはるかに簡単です。