9

短縮版

ユーザーをシャードに分割する場合、「ユーザー検索」を提供するにはどうすればよいですか? 明らかに、すべての検索がすべてのシャードにヒットすることは望んでいません。

ロングバージョン

シャードとは、複数のデータベースがあり、それぞれに全データの一部が含まれていることを意味します。(単純な) 例として、データベース UserA、UserB などには、名前が「A」、「B」などで始まるユーザーが含まれている可能性があります。データベース。戻ってきたユーザーがサインインすると、そのユーザーの名前をもう一度調べて、そのユーザーの情報を取得する正しいデータベースを判断します。

シャーディングと読み取りレプリケーションの利点は、読み取りレプリケーションが書き込みをスケーリングしないことです。マスターに送信されるすべての書き込みは、各スレーブに送信する必要があります。ある意味では、読み取り負荷が分散されていても、それらはすべて同じ書き込み負荷を担います。

一方、シャードは互いの書き込みを気にしません。Brian が UserB シャードにサインアップした場合、UserA シャードはそれについて知る必要はありません。Brian が Alex にメッセージを送信した場合、その事実を UserA シャードと UserB シャードの両方に記録できます。このようにして、Alex または Brian のいずれかがログインすると、すべてのシャードにクエリを実行することなく、送受信したすべてのメッセージを自分のシャードから取得できます。

ここまでは順調ですね。検索はどうですか?この例では、Brian が「Alex」を検索すると、UserA を確認できます。しかし、彼が姓の「Smith」で Alex を検索するとどうなるでしょうか。すべてのシャードにスミスがいます。ここから、次の 2 つのオプションが表示されます。

  1. アプリケーションで各シャードで Smiths を検索します。これは、ゆっくり (各シャードを連続してクエリする) または迅速に (各シャードを並行してクエリする) 行うことができますが、いずれにしても、すべてのシャードがすべての検索に関与する必要があります。読み取りレプリケーションが書き込みをスケーリングしないのと同じように、検索がすべてのシャードにヒットしても、検索はスケーリングされません。検索ボリュームが各シャードを圧倒するほど高くなる時期に達する可能性があり、シャードを追加しても検索ボリュームは同じになるため役に立ちません。
  2. それ自体がシャーディングに耐えられるある種のインデックス作成。たとえば、検索したい一定数のフィールドがあるとします: 名と姓です。UserA、UserB などに加えて、IndexA、IndexB などもあります。新しいユーザーが登録されると、そのユーザーを見つけてもらいたい各インデックスに追加します。そこで私は Alex Smith を IndexA と IndexS の両方に入れました。彼は "Alex" または "Smith" のいずれかで見つけることができますが、部分文字列はありません。この方法では、各シャードに対してクエリを実行する必要がないため、検索がスケーラブルになる可能性があります。

では、検索はスケーリングできますか? もしそうなら、この索引付けアプローチは正しいものですか? 他にある?

4

5 に答える 5

11

魔法の弾丸はありません。

各シャードを連続して検索することは、非常に長いレイテンシーが発生するため、明らかに問題外です。

そのため、必要に応じて並行して検索する必要があります。

2 つの現実的なオプションがあり、既にそれらをリストしました。インデックス作成と並列検索です。それらをどのように設計するかについて、もう少し詳しく説明させてください。

使用できる重要な洞察は、検索では完全な結果セットが必要になることはめったにないということです。結果の最初 (または n 番目) のページのみが必要です。そのため、応答時間を短縮するために使用できるかなりの余地があります。

索引付け

ユーザーが検索される属性がわかっている場合は、カスタムの別のインデックスを作成できます。各検索語の (shard, recordId) タプルを指す独自の逆インデックスを作成するか、データベースに保存することができます。遅延して非同期に更新します。アプリケーションの要件はわかりませんが、毎晩インデックスを再構築することさえ可能かもしれません (つまり、特定の日に最新のエントリがないことを意味しますが、それは問題ないかもしれません)。メモリに収まるように、このインデックスのサイズを最適化してください。必要に応じて、このインデックスを分割できることに注意してください。

当然のことながら、人々が のようなものを検索できる場合"lastname='Smith' OR lastname='Jones'"、Smith のインデックスを読み取り、Jones のインデックスを読み取り、結合を計算できます。すべての可能なクエリを保存する必要はなく、構築部分だけを保存する必要があります。

並列検索

検索はたまたま分散キー上にあるため、どのシャードを探すべきかわからない場合を除いて、すべてのクエリについて、すべてのシャードにリクエストを送信します。リクエストを非同期にします。最初のページに相当する結果を取得したらすぐにユーザーに返信します。残りを収集してローカルにキャッシュします。ユーザーが「次へ」をクリックすると、結果が準備され、サーバーに再度クエリを実行する必要がなくなります。このようにして、一部のサーバーが他のサーバーよりも時間がかかっている場合でも、それらのサーバーが要求を処理するのを待つ必要はありません。

その間、シャード サーバーの応答時間をログに記録して、不均一なデータや負荷分散に関する潜在的な問題を観察します。

于 2008-11-06T02:20:21.373 に答える
2

私はあなたがシャードについて話していると仮定しています: http://highscalability.com/unorthodox-approach-database-design-coming-shard

その記事を読めば、彼はまさにあなたの質問について詳しく説明していますが、長い答えを簡潔に言うと、カスタム アプリケーション コードを記述して、異種のシャードをまとめることができます。個々のシャードのクエリとシャードへのデータの挿入の両方で、スマート ハッシングを行うことができます。より具体的な答えを得るには、より具体的な質問をする必要があります。

于 2008-11-04T00:32:18.037 に答える
1

Sphinx ( http://www.sphinxsearch.com/articles.html ) を参照してください。分散検索をサポートしています。GigaSpaces には、並列クエリとマージのサポートがあります。これは、MySQL プロキシ ( http://jan.kneschke.de/2008/6/2/mysql-proxy-merging-resultsets ) でも実行できます。

シャード化されていないインデックス化された種類のものを構築することは、そもそもシャードの目的を打ち負かします:-) シャードが必要な場合、集中型インデックスはおそらく機能しません。

すべてのシャードを並行して攻撃する必要があると思います。結果をフィルタリング、ランク付け、ソート、グループ化し、すべてのシャードから結果をマージする必要があります。シャード自体が圧倒された場合は、通常の方法 (リシャード、スケールアップなど) を実行して、シャードを再び圧倒する必要があります。

于 2008-11-06T20:42:45.563 に答える
1

実際には、すべてのシャードにヒットするためにすべての検索が必要です。または、少なくともすべてのシャードからのデータを含むインデックスに対してすべての検索を実行する必要があります。つまり、同じことになります。

おそらく、ユーザーの単一のプロパティ、おそらくユーザー名のハッシュに基づいてシャードします。検索機能により、ユーザーがユーザーの他のプロパティに基づいて検索できる場合、クエリを満たすことができる単一のシャードまたはシャードのサブセットがないことは明らかです。シャードにはクエリに一致するユーザーが含まれる可能性があるためです。検索を実行する前にシャードを除外することはできません。つまり、すべてのシャードに対してクエリを実行する必要があります。

于 2008-11-04T00:37:56.433 に答える
0

RDBM は、テキスト検索には適していません。Solrを見たほうがずっといいでしょう。Solr とデータベースのパフォーマンスの差は、100 倍程度になります。

于 2012-02-11T01:40:25.343 に答える