pythonでRedisの大量データからttl一覧を取得したい(2)
Redisのキーってttl切れしても実はメモリ上には残ってて、volatile-lruとかが発生するまで残ってるんじゃね? getかttlとかで引けば消えるんじゃね?
っていう話が上がって、とりあえずscanしてttl引いてみよう、getしてみようという話。
スクリプト1
collect_key_by_pattern.py
概要
パターンマッチを指定してn件ずつscan
scan_result_${pattern}.txtにkeyを出力
INPUT/OUTPUT
IN/OUT | 値 | 備考 |
---|---|---|
INPUT | なし | |
OUTPUT | scan_result_${pattern}.txt |
引数
$n | 説明 | 例 | 備考 |
---|---|---|---|
1 | 対象のRedis endpoint | 127.0.0.1 | |
2 | scanに渡すmatchパターン | refresh_token | 成果物のファイル名に使われるので、「:」を渡すとファイル名にそのまま渡されて少しださい |
3 | scanに渡すrange | 1000 |
ソース
#!/usr/bin/env import sys import redis import logging INITIAL_CUR = 0 REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] or '127.0.0.1' MATCH_PATTERN = len(sys.argv) > 2 and sys.argv[2] or '' COUNT = len(sys.argv) > 3 and sys.argv[3] or '100' OUTPUT = 'scan_result_' + MATCH_PATTERN + '.txt' logger = logging.getLogger() logger.setLevel(10) # for file fh = logging.FileHandler(OUTPUT) logger.addHandler(fh) def utf8(byte): if byte: return str(byte, 'utf-8') if __name__ == '__main__': if len(sys.argv[1:]) < 3: sys.exit("Usage: %s <redis-endpoint> <match-pattern>" % sys.argv[0]) r = redis.StrictRedis(host=REDIS_HOST, port=ほげ) next_cur = INITIAL_CUR while True: res_scan = r.scan(cursor=next_cur, match=MATCH_PATTERN + '*', count=COUNT) # SCAN print(len(res_scan[1])) next_cur = res_scan[0] if res_scan[1]: for key in res_scan[1]: logger.info(utf8(key)) if next_cur == INITIAL_CUR: break
実行
$ python36 collect_key_by_pattern.py 127.0.0.1 refresh_token 1000 $
とくに出力はしない
成果物
$ head scan_result_refresh_token.txt refresh_token:76c1b0bca4097cb1d42d2aa9c694d1bdbce5cc94 refresh_token:299251bad808a5b71ef8b806c689182e328701d3 refresh_token:02be609d8f80183f22edca17217d06d43717d64f
スクリプト2
get_ttl.py
概要
key, ttlのフォーマットでファイル出力
ttl切れを判定し、あったらファイル出力
INPUT/OUTPUT
IN/OUT | 値 | 備考 |
---|---|---|
INPUT | scan_result_${pattern}.txt | |
OUTPUT | key_ttl.log, expired_keys.txt |
引数
$n | 説明 | 例 | 備考 |
---|---|---|---|
1 | 対象のRedis endpoint | 127.0.0.1 | |
2 | 検索するキーを記載したファイル | scan_result_laravel.txt |
ソース
#!/usr/bin/env #coding:utf-8 import sys import redis import pdb import logging REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] INPUT_FILE = len(sys.argv) > 2 and sys.argv[2] KEY_TTL = 'key_ttl.log' #logger1========================================== logger = logging.getLogger('LoggingTest') logger.setLevel(10) fh = logging.FileHandler(KEY_TTL) logger.addHandler(fh) #logger1========================================== #logger2========================================== logger_for_output = logging.getLogger('logger_for_output') logger_for_output.setLevel(10) # for file fh = logging.FileHandler('expired_keys.txt') logger_for_output.addHandler(fh) #logger2========================================== def utf8(byte): if byte: return str(byte, 'utf-8') if __name__ == '__main__': if len(sys.argv[1:]) < 2: sys.exit("Usage: %s <redis-endpoint> <input file>" % sys.argv[0]) r = redis.StrictRedis(host=REDIS_HOST, port=ほげ) # keyを元にttlを抽出、"key ttl"のフォーマットで中間ファイルを出力 with open(INPUT_FILE) as f: for key in f: key_ = key.rstrip('\n') res_ttl = r.ttl(key_) # TTL logger.info('%s %s', key_, res_ttl) # 中間ファイルからkey, ttlを抽出して、ttl切れがないか確認 with open(KEY_TTL) as f: for key in f: if key.split()[1] <= '0': logger_for_output.info(key.rstrip('\n'))
実行
$ python36 get_ttl.py 127.0.0.1 scan_result_refresh_token.txt $
特に何も出ない
成果物
ttlが設定されていないキーが出力された。(テストデータ)
$ head expired_keys.txt refresh_token:cfa85abcc28d616f46c78f3c289609db0a1b1526 -1 refresh_token:182433e52a42776f95ff871a79f21e2a3c4ee9c17 -1 refresh_token:182433e52a42776f95ff871a79f21e2a3c4ee9c11 -1
あとで、実際にRedisにデータを突っ込んで試してみよう。
ダメでも、scanしてRedis内のキーの割合を算出する程度の役には立つだろう。。。