3

これは一般的な設計上の問題です。ユーザーが値を入力してタブアウトしたときに、ユーザー名フィールドの一意性を検証したいと思います。Ajax検証を実行し、サーバーから応答を取得します。これはすべて非常に標準的です。さて、巨大なユーザーデータベースがある場合はどうなりますか?この状況に対処する方法は?1億5000万のユーザー名の中にユーザー名「foozbarz」が存在するかどうかを知りたいですか?

  1. データベースクエリは問題外です[編集]-ユーザー名データベースを1回読み取り、キャッシュ/ハッシュにデータを入力して検索を高速化します(EmilVikströmのポイントを明確にするため)
  2. インメモリデータベースはどちらも役に立ちません
  3. すべてのユーザー名を保存するために、メモリ内のハッシュ(またはcache / memcache)を保持します-ユーザー名は簡単にハッシュでき、ルックアップは非常に高速になります。ただし、これにはいくつかの問題があります。ハッシュのサイズ-ハッシュサイズを減らすことができるように最適化できますか?b。ハッシュ/キャッシュの更新頻度(検証中にユーザーが追加される可能性があります)
  4. いくつかの基準に基づいてユーザー名テーブルをシャーディングします(例:テーブルusername_1のABなど)-この提案をありがとうpiotrek

または、他のより良いアプローチはありますか?

4

5 に答える 5

2

単純にデータを分割してみませんか? 1 億 5,000 万人以上のユーザーを抱えている/計画している場合、そのための予算がある/あると思います。始めたばかり (2,000 人のユーザー) の場合は、従来の方法でデータベースの単純なインデックス検索を行います。非常に多くのユーザーがいて、パフォーマンスの問題を観察し、これがデータベース (www サーバーなどではなく) によるものであると判断した場合は、単純に別のデータベースを配置します最初のものには、a から m までの名前のユーザーがいて、もう一方には残ります。ハッシュなどの他の基準を選択して、データのバランスを取ることができます。さらに必要な場合は、データベースを追加します。しかし、現在それほど多くのユーザーがいない場合は、時期尚早の最適化を行わないことをお勧めします。この量のデータではボトルネックになることがたくさんあります

于 2012-06-23T10:55:15.367 に答える
1

あなたの 1 番目の基準には欠陥があります。なぜなら、これはまさにデータベース システムの目的であるデータの保存と管理のためだからです。読むつもりがないのに、なぜユーザー名を含むテーブルを持っているのですか?

最初に行うことは、インデックスを追加してデータベース システムを改善するHASHことです。データベース システムがサポートしている場合はインデックスを追加することをお勧めします。このパフォーマンスに近いものを自分で書くのは難しいでしょう。

これで十分でない場合は、データベースのスケーリングを開始する必要があります。たとえば、クラスター化されたデータベースを構築したり、テーブルを複数のサブテーブルに分割したりします。

私が公平だと思うのは、データベースの前にキャッシングを実装することですが、単一の名前に対してです。すべてのユーザー名が衝突を試みるわけではないため、衝突が通常発生する小さなサブセットをキャッシュすることができます。USER の衝突ステータスをチェックするための単純なアルゴリズム:

  1. USER がキャッシュに存在するかどうかを確認します。そうであれば:
    1. キャッシュ内の USER の「最後にチェックされた」タイムスタンプを設定します
    2. あなたは終わり、USERは衝突しています
  2. データベースで USER を確認します。存在する場合:
    1. USER をキャッシュに追加する
    2. キャッシュがいっぱいの場合 (すべての X スロットが使用されている場合)、使用頻度の最も低いユーザー名をキャッシュから削除します (キャッシュのプルーニングを最小限に抑えたい場合は、使用頻度の最も低い Y 個のユーザー名を削除します)。
    3. あなたは終わり、USERは衝突しています
  3. キャッシュまたはデータベースと一致しなかった場合は、完了であり、USER は衝突ではありません。

もちろん、競合状態を避けるために、データベースには UNIQUE 制約が必要です。

于 2012-06-23T11:36:24.587 に答える
1

取得した名前を保存する場所である種のハッシュを行うことについては、おそらく正しいでしょう。明らかに、ハッシュされていないということは、それが無料であることを意味します。

すべきでないことは、その検証に頼ることです。ユーザーが [登録] を押してから、ユーザーが名前が空いているかどうかを確認するまでに、かなりの時間がかかる場合があります。

公平を期すために、ここで問題が 1 つだけあります。それは、1 億 5000 万のユーザーを獲得できるかどうかを本当に心配する必要があるかどうかの考慮事項です。多くの場合、スケーラビリティが問題になりますが、これが一晩で発生しない限り、問題が発生する前により良いソリューションに交換できる可能性があります。

第二に、両方のユーザーがこの名前を無料で取得し、次に 1 人がそれを取得することを心配します。まず、その可能性はかなり低いです。第二に、ユーザーが検証済みの名前で [OK] をクリックして USERNAME TAKEN を取得しない方法でこれを「解決」することを考えることができる唯一の方法は、a) ユーザーが最後に検証したものを記憶し、それを保存し、他の誰かがそれを登録した場合その間、AJAX を使用して名前フィールドを take に変更し、ユーザーに通知します。これをしないでください。多くの無駄なサイクルと、実装するのに非常に多くの労力がかかります。b) ユーザーがユーザー名を検証すると、ユーザー名を短時間ロックします。これにより、実際には使用されていないのに、多くの無料のユーザー名が使用されることになります。あなたもおそらくこれを望んでいません。

これに対する最も簡単な解決策は、ユーザーが実際に [OK] をクリックしたときにハッシュ値をテーブルに入れることですが、その前に、名前が再度存在するかどうかを確認してください。その場合は、USERNAME TAKEN を付けてユーザーを送り返します。誰かが名前をめぐって他の誰かと競争する可能性は本当に非常に低く、バリデーター(チェックの時点で名前は無料でした)がユーザーに「嘘をついた」方法について大騒ぎする人はいないと思います.

基本的に、唯一の問題は、ニックネームをどのように保存するかです。

于 2012-06-23T06:01:17.547 に答える
0

1億5000万人以上のユーザーがいる場合は、次のような機能を導入する必要があります。

  1. ユーザーが存在することを確認し、見つからない場合は通知します
  2. パスワードが正しいことを確認し、正しくない場合は通知します
  3. ユーザーのデータを取得します

あなたが抱えるこの問題は、それを解決しなければなりません。おそらく、ユーザーのクエリに似たものがあります。セッションに大きく依存している場合でも、「1億5000万以上のプールから多くの中からセッションXを見つける」という問題が発生します。これは、「1億5000万以上のプールから多くの中からユーザーXを見つける」と構造的に同じです。

より大きな問題を解決すると、現在の問題はそのステップ1にすぎません。

そこで、スケーラブルなデータベースソリューション(おそらくNoSQLソリューション)をチェックアウトし、それを使用して「可用性チェック」を実装します。

あなたはで終わるかもしれません

retrieveUserData(user, password = None)

これは、ユーザーとパスワードが有効で正しい場合にユーザー情報を返します。可用性チェックでは、パスワードを送信せず、ユーザー名が使用可能な場合はUserNotFound例外が発生することを予期します。

于 2012-06-23T09:11:22.077 に答える
0

従来のルートを使用する場合は、適切なインデックスを使用してデータベースの検索を改善できます。

また、大規模なデータ セットでのルックアップのレイテンシが非常に低い ElasticSearch などを使用することもできます。

于 2012-06-23T05:56:40.223 に答える