24

私は Redis DB の初心者です。いくつかのドキュメントを読み、インターネット上のいくつかの例を調べ、stackoverflow.com をスキャンした後、Redis は非常に高速で、適切に拡張できることがわかりましたが、これには、データがどのようになるかを考えなければならないという代償が伴います。設計時にアクセスされ、どのような操作を受ける必要があるかを示します。これは理解できますが、昔ながらの単純な SQL では非常に簡単でしたが、遅いデータ検索について少し混乱しています。KEY コマンドを使用して 1 つの方法で実行できますが、これは O(N) 操作であり、O(log(N)) ではありません。したがって、Redis の利点の 1 つを失うことになります。

経験豊富な同僚はここで何と言っていますか?

ユース ケースの例を見てみましょう。100.000 人のデータを名前、電話番号で検索する必要があります。

これには、次の構造を使用します。

1. SET for storing all persons' ids {id1, id2, ...} 
2. HASH for each person to store personal data and name it 
like map:<id> e.g. map:id1{name:<name>, phone:<number>, etc...}

解決策 1:

1. HASH for storing all persons' ids but the key should be the phone number
2. Then with the command KEY 123* all ids could be retrieved who have a phone number 
sarting with 123. On basis of the ids also the other personal data could be retrieved.
3. So forth for each data to be searched for a separate HASH should be created.

ただし、このソリューションの主な欠点は、HASH 内の電話番号と ID の割り当てが明確になるように、属性値も一意でなければならないことです。一方、O(N)ランタイムは理想的ではありません。

また、これは必要以上のスペースを使用し、KEY コマンドはアクセス パフォーマンスを低下させます。( http://redis.io/commands/keys )

それはどのように正しい方法で行われるべきですか?また、ID が ZSET に入り、検索に必要なデータがスコアになる可能性があると想像することもできますが、これにより、検索ではなく範囲でのみ作業が可能になります。

また、事前にありがとう、よろしく、タマス

回答の要約: 実際、どちらの回答も、Redis はキーの値を検索するようには設計されていないと述べています。このユースケースが必要な場合は、元のソリューションまたは以下のソリューションに示すように、回避策を実装する必要があります。

Eliによる以下のソリューションは、キーへのアクセスが一定であると見なすことができるため、元のソリューションよりもパフォーマンスがはるかに優れています.IDのリストのみを反復処理する必要があるため、これによりO(const)ランタイムが得られます。このデータ モデルでは、ある人が別の人と同じ電話番号を持っている可能性もあり、名前などについても同様です。したがって、1 対 n の関係も可能です(古い ERD 用語で言います)。

このソリューションの欠点は、私のものよりもはるかに多くのスペースを消費することと、最初の数字しかわかっていない電話番号を検索できないことです。

両方の応答をありがとう。

4

4 に答える 4

28

Redis は、非常に高い頻度でデータにアクセスして更新する必要があり、データ構造 (ハッシュ、セット、リスト、文字列、または並べ替えられたセット) を使用するメリットがあるユース ケース向けです。非常に特殊なユースケースを満たすために作られています。非常に柔軟な検索などの一般的なユースケースがある場合は、エラスティック検索や SOLR など、この目的のために構築されたものの方がはるかに優れています。

とはいえ、これを Redis で行う必要がある場合は、次のようにします (ユーザーが名前と電話番号を共有できると仮定します)。

name:some_name -> set([id1, id2, etc...])
name:some_other_name -> set([id3, id4, etc...])

phone:some_phone -> set([id1, id3, etc...])
phone:some_other_phone -> set([id2, id4, etc...])

id1 -> {'name' : 'bob', 'phone' : '123-456-7891', etc...}
id2 -> {'name' : 'alice', 'phone' : '987-456-7891', etc...}

この場合、すべての名前 (「name:」で始まる) とすべての電話番号 (「phone:」で始まる) に対して新しいキーを作成します。各キーは、ユーザーに必要なすべての情報を含む一連の ID を指します。たとえば、電話を検索する場合は、次のようにします。

HGETALL 'phone:123-456-7891'

次に、結果をループして、選択した言語でそれぞれの情報 (この例では名前) を返します (Redis ボックスのサーバー側の Lua でこのすべてを実行して、さらに高速化し、ネットワークのバックアンド-を回避できます)。必要に応じて):

for id in results:
    HGET id 'name'

ここでのコストO(m)m、指定された電話番号を持つユーザーの数です。速度が最適化されているため、これは Redis で非常に高速な操作になります。おそらく物事をそれほど速くする必要はなく、柔軟な検索を好むので、あなたの場合はやり過ぎになりますが、これがあなたのやり方です。

于 2013-06-19T21:04:04.543 に答える