獲取沒有設置TTL的key
一 前言
在運維Redis的時候,總會遇到使用不規範的業務設計,比如沒有對key設置ttl,進而導致內存空間吃緊,通常的解決方法是在slave上dump 出來所有的key ,然後對文件進行遍歷再分析。遇到幾十G的Redis實例,dump + 分析 會是一個比較耗時的操作,為此,我開發了一個小腳本直接連接Redis 進行scan 遍歷所有的key,然後在檢查key的ttl,將沒有ttl的key輸出到指定的文件裡面。
二 代碼實現
# encoding: utf-8
"""
author: yangyi@youzan.com
time: 2018/4/26 下午4:34
func: 獲取資料庫中沒有設置ttl的 key
"""
importredis
importargparse
importtime
importsys
classShowProcess:
"""
顯示處理進度的類
調用該類相關函數即可實現處理進度的顯示
"""
i =# 當前的處理進度
max_steps =# 總共需要處理的次數
max_arrow =50# 進度條的長度
# 初始化函數,需要知道總共的處理次數
def__init__(self,max_steps):
self.max_steps = max_steps
self.i =
# 顯示函數,根據當前的處理進度i顯示進度
# 效果為[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]100.00%
defshow_process(self,i =None):
ifiis notNone:
self.i = i
else:
self.i +=1
num_arrow =int(self.i *self.max_arrow /self.max_steps)# 計算顯示多少個">"
num_line =self.max_arrow - num_arrow# 計算顯示多少個"-"
percent =self.i *100.0/self.max_steps# 計算完成進度,格式為xx.xx%
process_bar ="["+">"* num_arrow +" "* num_line +"]"
+"%.2f"% percent +"%"+"
"# 帶輸出的字元串,"
"表示不換行回到最左邊
sys.stdout.write(process_bar)# 這兩句列印字元到終端
sys.stdout.flush()
defclose(self,words="done"):
print""
printwords
self.i =
defcheck_ttl(redis_conn,no_ttl_file,dbindex):
start_time = time.time()
no_ttl_num =
keys_num = redis_conn.dbsize()
print"there are keys in db ".format(num=keys_num,index=dbindex)
process_bar = ShowProcess(keys_num)
withopen(no_ttl_file,"a")asf:
forkeyinredis_conn.scan_iter(count=1000):
process_bar.show_process()
ifredis_conn.ttl(key) == -1:
no_ttl_num +=1
ifno_ttl_num
f.write(key+"
")
else:
continue
process_bar.close()
print"cost time(s):",time.time() - start_time
print"no ttl keys number:",no_ttl_num
print"we write keys with no ttl to the file: %s"% no_ttl_file
defmain():
parser = argparse.ArgumentParser()
parser.add_argument("-p",type=int,dest="port",action="store",help="port of redis ")
parser.add_argument("-d",type=str,dest="db_list",action="store",default=,
help="ex : -d all / -d 1,2,3,4 ")
args = parser.parse_args()
port = args.port
ifargs.db_list =="all":
db_list = [iforiinxrange(,16)]
else:
db_list = [int(i)foriinargs.db_list.split(",")]
forindexindb_list:
try:
pool = redis.ConnectionPool(host="127.0.0.1",port=port,db=index)
r = redis.StrictRedis(connection_pool=pool)
exceptredis.exceptions.ConnectionErrorase:
printe
else:
no_ttl_keys_file ="/tmp/__no_ttl_keys.txt".format(port=port,db=index)
check_ttl(r,no_ttl_keys_file,index)
if__name__ =="__main__":
main()
注意:
代碼裡面對沒有ttl的key的輸出做了限制,大家使用的時候可以調整閾值 或者去掉 全部輸出到指定的文件裡面。歡迎大家使用,並給出功能或者演算法上的改進措施。
TAG:大千世界 |