redis のキーを走査する


redis はシングルプロセスで動くので、
大量のキーを走査する目的で keys * とかやるとえらいことになるので、
代わりに scan 族を使うとよさげ、っていう話。

カーソルは0からスタートして、再度0になると1順したことになるので、全件走査はこんな感じ。
必ず count で指定した件数が取れるわけでもないらしい。

他に set, hash, zset に対するscanもあって、使い方はだいたい同じ。

意外とググっても情報出てこないのでメモ。

python

import redis

r = redis.StrictRedis()

cr = 0
acc = 0
while True:
    cr, keys = r.scan(cr, match="*", count=10000)
    acc += len(keys)
    print(cr, len(keys), acc)

    if cr == 0:
        break

print(r.dbsize())
stdout
60736 10001 10001
90528 10000 20001
827920 10001 30002

...(中略)

832503 10000 870045
864591 10000 880045
858799 10001 890046
853023 10000 900046
100191 10000 910046
529855 10001 920047
0 8407 928454
928454

redis-cli

だとこれで自動的に1件ずつscanしてくれる。

$ redis-cli --scan --pattern '*'
MONITOR
1487148044.325432 [0 172.17.0.1:35426] "SCAN" "877248" "MATCH" "*"
1487148044.325922 [0 172.17.0.1:35426] "SCAN" "320192" "MATCH" "*"
1487148044.331590 [0 172.17.0.1:35426] "SCAN" "385728" "MATCH" "*"
1487148044.332199 [0 172.17.0.1:35426] "SCAN" "70336" "MATCH" "*"
1487148044.332777 [0 172.17.0.1:35426] "SCAN" "824000" "MATCH" "*"
1487148044.333387 [0 172.17.0.1:35426] "SCAN" "496320" "MATCH" "*"
1487148044.333901 [0 172.17.0.1:35426] "SCAN" "53952" "MATCH" "*"
1487148044.349686 [0 172.17.0.1:35426] "SCAN" "381632" "MATCH" "*"
...(略)

先頭から何件か欲しい場合はパイプで head -n 1000 とかに流すとよい。
tailだと駄目だけど。

こっちの方が詳しい

けどまぁいいか。もう書いちゃったし。