1

2つのセカンダリインデックスを持つ「メッセージ」テーブルがあるとします。

  • "recipient_id"
  • "sender_id"

「メッセージ」テーブルを「recipient_id」でシャーディングしたい。特定の受信者に送信されたすべてのメッセージを取得する方法では、1つのシャードにクエリを実行するだけで済みます。

しかし同時に、特定の送信者から送信されたすべてのメッセージを要求するクエリを作成できるようにしたいと思います。ここで、そのクエリを「メッセージ」テーブルのすべてのシャードに送信したくありません。これを行う1つの方法は、データを複製し、「message_by_sender」テーブルを「sender_id」でシャーディングすることです。

このアプローチの問題は、メッセージが送信されるたびに、「message」テーブルと「message_by_sender」テーブルの両方にメッセージを挿入する必要があることです。

しかし、「message」に挿入した後、「message_by_sender」への挿入が失敗した場合はどうなりますか?その場合、メッセージは「message」に存在しますが、「message_by_sender」には存在しません。

メッセージが「message」に存在する場合、2フェーズコミットに頼らずに「message_by_sender」にも存在することを確認するにはどうすればよいですか?

これは、データベースをシャーディングする人にとっては非常に一般的な問題であるに違いありません。どのように対処しますか?

4

1 に答える 1

1

この問題に「特効薬」はありません。いくつかのオプション:

  1. メッセージキューを使用して変更を投稿します。最終的には、変更によって別のパーティションに反映されます。
  2. テーブルに「インデックスエントリが必要」行を作成するメッセージテーブルパーティションにトリガーを設定します。他の何かが定期的にこれをスキャンしてインデックスを作成します。

Google App Engineでの分散トランザクションの実行に関する次のブログエントリを読むことをお勧めします:http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine。基本的に、2phase commitやPaxosなどが必要ない場合は、結果整合性のあるモデルを使用する必要があります。

-デイブ

于 2010-05-02T03:51:53.383 に答える