Redis Scanの使い方及びSpring redisのピット
6614 ワード
SpringRedisTemplateは、このScanをカプセル化し、使用例を示します(最新ライブラリspring-data-redis-1.8.1.1.RELEASE):
注意Cursorは必ず閉じることができません.以前のバージョンでは、ここでCursorは手動で閉じる必要がありましたが、1.8からです.0開始、手動で閉じることはできません!異常を報告します.
ScanOptionsには2つのパラメータがあり、1つはmatchで、もう1つはcountで、それぞれscanコマンドの2つのパラメータに対応しています.
Scanコマンドソース:
RedisのSCANオペレーションは、全体的なデータ設計のため、特に正確なscanオペレーションを提供することができず、「can't guarantee,just domy best」の実装にすぎないことがわかります.はキー空間の遍歴操作を提供し、カーソル、複雑度O(1)をサポートし、全体的に遍歴するにはO(N)しか必要ない. は、結果パターンマッチングを提供する. は、一度に返されるデータバー数の設定をサポートしていますが、hintsだけで、返されることが多い場合があります. 弱い状態で、すべての状態はクライアントがカーソルを維持する必要があるだけです. は完全なスナップショット遍歴を提供できません.つまり、データの変更があれば、変更に関連するデータ遍歴ができない場合があります. が返すたびに返されるデータの数は一定ではなく、内部に極度に依存して実現される. が返すデータは重複する可能性があり、アプリケーション層は再入力ロジックを処理することができる必要がある.上記のサンプルコードでは、redisTemplate.executeメソッドはSetであり、返されたkeyの重量除去 に相当する. countは、スキャンごとのkey個数であり、結果セット個数ではない.countはスキャンデータ量の大きさによって異なり、Scanはロックされていないが、百万以上のデータ量レベルでの検索効率を保証することはできない.countは小さすぎてはいけません.ネットワークのインタラクションが多くなります.countはできるだけ大きくしなければなりません.検索結果セット1万以内では、収集するサイズと同じ に直接設定することを推奨する.
Set
注意Cursorは必ず閉じることができません.以前のバージョンでは、ここでCursorは手動で閉じる必要がありましたが、1.8からです.0開始、手動で閉じることはできません!異常を報告します.
ScanOptionsには2つのパラメータがあり、1つはmatchで、もう1つはcountで、それぞれscanコマンドの2つのパラメータに対応しています.
Scanコマンドソース:
/* Handle the case of a hash table. */
ht = NULL;
if (o == NULL) {//
ht = c->db->dict;
} else if (o->type == REDIS_SET && o->encoding == REDIS_ENCODING_HT) {
ht = o->ptr;
} else if (o->type == REDIS_HASH && o->encoding == REDIS_ENCODING_HT) {
ht = o->ptr;
count *= 2; /* We return key / value for this type. */
} else if (o->type == REDIS_ZSET && o->encoding == REDIS_ENCODING_SKIPLIST) {
zset *zs = o->ptr;
ht = zs->dict;
count *= 2; /* We return key / value for this type. */
}
// redis ziplist, intset , 。 else if 。 key 。
if (ht) {// , intset, ziplist
void *privdata[2];
/* We pass two pointers to the callback: the list to which it will
* add new elements, and the object containing the dictionary so that
* it is possible to fetch more data in a type-dependent way. */
privdata[0] = keys;
privdata[1] = o;
do {
// , cursor , keys 。
cursor = dictScan(ht, cursor, scanCallback, privdata);
} while (cursor && listLength(keys) < count); } else if (o->type == REDIS_SET) {
int pos = 0;
int64_t ll;
while(intsetGet(o->ptr,pos++,&ll))// set , intset, 。
listAddNodeTail(keys,createStringObjectFromLongLong(ll));
cursor = 0;
} else if (o->type == REDIS_HASH || o->type == REDIS_ZSET) {// ziplist , , 。
unsigned char *p = ziplistIndex(o->ptr,0);
unsigned char *vstr;
unsigned int vlen;
long long vll;
while(p) {// , 。 cursor 0 。
ziplistGet(p,&vstr,&vlen,&vll);
listAddNodeTail(keys,
(vstr != NULL) ? createStringObject((char*)vstr,vlen) : createStringObjectFromLongLong(vll));
p = ziplistNext(o->ptr,p);
}
cursor = 0;
} else {
redisPanic("Not handled encoding in SCAN.");
}
RedisのSCANオペレーションは、全体的なデータ設計のため、特に正確なscanオペレーションを提供することができず、「can't guarantee,just domy best」の実装にすぎないことがわかります.