26

複数のPostgreSQLサーバーに基づくDjangoプロジェクトがあります。

Instagram で使用されているのと同じシャーディング ロジックを使用して、これらのデータベース サーバー間でユーザーをシャーディングする必要があります

ユーザー ID => 論理シャード ID => 物理シャード ID => データベース サーバー => スキーマ => ユーザー テーブル

  • 論理シャード ID は、ユーザー ID (ユーザー ID に埋め込まれた 13 ビット) から直接計算されます。
  • 論理シャード ID から物理シャード ID へのマッピングはハードコードされています (一部の構成ファイルまたは静的テーブルで)。
  • 物理シャード ID からデータベース サーバーへのマッピングもハード コーディングされています。この時点で、 Instagram はPgbouncerを使用して、プールされたデータベース接続を適切なデータベース サーバーに取得します。
  • 各論理シャードは独自のPostgreSQL スキーマに存在します(PostgreSQL に慣れていない方のために説明すると、これはテーブル スキーマではなく、 MySQL の「データベース」に似た名前空間のようなものです)。スキーマは単に「shardNNNN」のような名前が付けられます。ここで、NNNN は論理シャード ID です。
  • 最後に、適切なスキーマのユーザー テーブルがクエリされます。

Django でこれをできるだけ簡単に実現するにはどうすればよいですか?

理想的には、次のような Django コードを書きたいと思っています。

インスタンスのフェッチ

# this gets the user object on the appropriate server, in the appropriate schema:
user = User.objects.get(pk = user_id)

関連オブジェクトの取得

# this gets the user's posted articles, located in the same logical shard:
articles = user.articles

インスタンスの作成

# this selects a random logical shard and creates the user there:
user = User.create(name = "Arthur", title = "King")
# or:
user = User(name = "Arthur", title = "King")
user.save()

ユーザーを名前で検索する

# fetches all relevant users (kings) from all relevant logical shards
# - either by querying *all* database servers (not good)
# - or by querying a "name_to_user" table then querying just the
#   relevant database servers.
users = User.objects.filter(title = "King")

さらに複雑なことに、ストリーミング レプリケーションを使用して、すべてのデータベース サーバーのデータを複数のスレーブ サーバーに複製します。マスターは書き込みに使用し、スレーブは読み取りに使用する必要があります。

Django は自動データベース ルーティングのサポートを提供しますが、これはおそらく上記のほとんどに十分ですがUser.objects.get(pk = user_id)、ルーターがクエリ パラメータにアクセスできないため、ユーザー ID が何であるかがわからないため、私は行き詰まっています。コードは User モデルを読み取ろうとしています。

シャーディングには制限があり、実際には非常に複雑になるため、シャーディングはおそらく最後の最適化手段としてのみ使用する必要があることを十分に認識しています。ほとんどの人はシャーディングを必要としません。最適化されたマスター/スレーブ アーキテクチャは、非常に長い道のりです。しかし、シャーディング必要だとしましょう。

要するに、Django でできるだけ簡単にデータを分割するにはどうすればよいでしょうか?

ご親切にありがとうございました。

ノート

非常によく似た既存の質問がありますが、私見では一般的すぎて正確な例がありません。私が興味を持っている特定のシャーディング手法 (Instagram のやり方) に絞り込みたかったのです。

4

3 に答える 3

9

Mike Clarke は最近 PyPgDay で、Disqus が Django と PostgreSQL を使用してユーザーをシャード化する方法について講演しました。彼は、彼らがどのようにそれを行うかについてのブログ投稿を書きました.

Postgres データベースをシャーディングする場合、いくつかの戦略を採用できます。Disqus では、テーブル名に基づいてシャードすることを選択しました。Django によって生成された元のテーブル名が comments_post である場合、シャーディング ツールは SQL を書き直してテーブル comments_post_X をクエリします。ここで、X は一貫したハッシュ スキームに基づいて計算されたシャード ID です。これらのテーブルはすべて、単一のデータベース インスタンス上の単一のスキーマに存在します。

さらに、シャード方法を示すサンプル アプリケーションの一部としていくつかのコードをリリースしました。

于 2013-04-09T15:40:34.163 に答える
2

あなたは本当にこの質問をする立場になりたくない. ユーザー ID でシャーディングしている場合は、おそらく名前で検索したくないでしょう。

データベースをシャーディングしている場合、アプリケーションから見えなくなることはなく、最終的にスキーマの変更が必要になる可能性があります。

SkyToolsが役に立つかもしれません- PL/Proxyを読んでください。これは、Skype がデータベースを分割する方法です。

于 2012-08-02T20:51:17.547 に答える