5

何百万もの要素を持つ Redis-Hash があり、常に新しい要素が追加されています。PHP では、エンドレス ループを実行して、1 つの要素を取得、処理、削除します。これにより、既存の要素のキーを取得する必要があります (できれば、ハッシュに挿入された最初の要素である FiFo)。

while($redis->hlen()) {
    $key = ???
    // process $key    
}

RANDOMKEYとコマンドは知ってSRANDMEMBERいますが、ハッシュのキーを取得する方法が見つかりませんでした。HGETALLハッシュのHKEYSサイズが原因で、どちらもオプションではありません。順次処理が必要です。助けていただければ幸いです。

4

1 に答える 1

6

特定のハッシュ オブジェクトのランダムな項目 (または最初または最後) にアクセスするためのトリックはありません。

ハッシュ オブジェクトを反復処理する必要がある場合、いくつかの可能性があります。

  • 最初のものは、スライスできる別のデータ構造 (リストや zset など) でハッシュを補完することです。ハッシュに項目を追加する (そしてそれらを削除するために反復する) だけの場合は、リストで十分です。アイテムを追加/削除/更新できる場合 (およびそれらを繰り返し削除できる場合)、zset が必要です (タイムスタンプをスコアとして入力します)。zset の両方のリストをスライス (lrange、zrange、zrangebyscore) できるため、チャンクごとに簡単に繰り返し、両方のデータ構造を同期して維持できます。

  • 2 つ目は、リストやセット (lpop、rpop、spop) などの pop のような操作をサポートする別のデータ構造でハッシュを補完することです。ハッシュ オブジェクトを反復処理する代わりに、二次構造からすべてのオブジェクトをポップアウトし、それに応じてハッシュ オブジェクトを維持できます。繰り返しますが、両方のデータ構造を同期させる必要があります。

  • 3 つ目は、ハッシュ オブジェクトを多くの部分に分割することです。キーは 1 回だけ保存され、Redis はziplist のメモリ最適化を利用できるため、これは実際にはメモリ効率が良いです。

したがって、ハッシュを次のように保存する代わりに:

myobject -> { key1:xxxx, key2:yyyyy, key3:zzzz }

保存できます:

myobject:<hashcode1> -> { key1:xxxx, key3:zzzz }
myobject:<hashcode2> -> { key2:yyyy }
...

追加のハッシュコードを計算するには、適切な分散を提供する任意のハッシュ関数をキーに適用できます。上記の例では、key1 と key3 が同じ hashcode1 値を持ち、key2 が hashcode2 値を持つと想定しています。

この種のデータ構造の詳細については、次を参照してください。

Redis のメモリ使用量はデータの 10 倍

ハッシュ関数の出力カーディナリティは、ハッシュ オブジェクトごとの項目数が特定の値に制限されるように計算する必要があります。たとえば、ハッシュ オブジェクトごとに 100 個のアイテムを持つことを選択し、100 万個のアイテムを保存する必要がある場合、10K のカーディナリティが必要になります。カーディナリティを制限するには、汎用ハッシュ関数でモジュロ演算を使用するだけで十分です。

利点は、メモリがコンパクトになり (ziplist を使用)、ハッシュ オブジェクトすべてに対して hgetall+del をパイプライン処理することで、ハッシュ オブジェクトを簡単に破壊的に反復できることです。

hgetall myobject:0
... at most 100 items will be returned, process them ...
del myobject:0
hgetall myobject:1
... at most 100 items will be returned, process them ...
del myobject:1
...

したがって、ハッシュ関数の出力カーディナリティによって決定される粒度でチャンクごとに繰り返すことができます。

于 2013-06-20T17:36:04.870 に答える