redis中查找大key方法匯總


  redis作為一個高性能內存數據庫,在實際業務中應用的非常廣泛,雖然redis的性能很好,但是在實際使用過程中,如果使用不當,也會造成一些性能問題,比如數據中存在大key。什么是大key?顧名思義就是單個key中的數據比較大,通常來說,單個key的value值不會很大,這種情況下,key的讀取,刪除操作不會影響性能,如果value過大,讀取或刪除會相對耗時,大家都知道,redis是單線程,耗時操作就會阻塞其它請求,給性能上帶來一些影響。所以,不管是作為開發還是運維人員,使用redis都應該經常關注數據中有沒有大key,今天就說說怎樣發現數據中的大key。

方法對比

1.自帶命令redis-cli --bigkeys
該命令是redis自帶,但是只能找出五種數據類型里最大的key。很明顯,這並不能幫助我們去發現整個數據里的大key,所以一般不使用,執行后如下圖:

2.python掃描腳本
這是根據腳本去掃描redis中的key,網上一搜就能找到,經實測發現,該腳本獲取的大key准確度不高,更確切的說並不是獲取的key的大小,而是key值的長度,比如hash類型,獲取的是hash中的字段數,string類型,獲取的是value的字符串長度,元素個數多並不能代表占用內存多。
find_bigkeys.py文件內容:

import sys
import redis
def check_big_key(r, k):
   bigKey = False
   length = 0 
   try:
     type = r.type(k)
     if type == "string":
       length = r.strlen(k)
     elif type == "hash":
       length = r.hlen(k)
     elif type == "list":
       length = r.llen(k)
     elif type == "set":
       length = r.scard(k)
     elif type == "zset":
       length = r.zcard(k)
   except:
     return
   if length > 102400: #key的長度條件,可更改該值
     bigKey = True
   if bigKey :
     print db,k,type,length
def find_big_key_normal(db_host, db_port, db_password, db_num):
   r = redis.StrictRedis(host=db_host, port=db_port, password=db_password, db=db_num)
   for k in r.scan_iter(count=1000):
     check_big_key(r, k)
def find_big_key_sharding(db_host, db_port, db_password, db_num, nodecount):
   r = redis.StrictRedis(host=db_host, port=db_port, password=db_password, db=db_num)
   cursor = 0
   for node in range(0, nodecount) :
     while True:
       iscan = r.execute_command("iscan",str(node), str(cursor), "count", "1000")
       for k in iscan[1]:
         check_big_key(r, k)
       cursor = iscan[0]
       print cursor, db, node, len(iscan[1])
       if cursor == "0":
         break;
if __name__ == '__main__':
   if len(sys.argv) != 4:
      print 'Usage: python ', sys.argv[0], ' host port password '
      exit(1)
   db_host = sys.argv[1]
   db_port = sys.argv[2]
   db_password = sys.argv[3]
   r = redis.StrictRedis(host=db_host, port=int(db_port), password=db_password)
   nodecount = 1
   keyspace_info = r.info("keyspace")
   for db in keyspace_info:
     print 'check ', db, ' ', keyspace_info[db]
     if nodecount > 1:
       find_big_key_sharding(db_host, db_port, db_password, db.replace("db",""), nodecount)
     else:
       find_big_key_normal(db_host, db_port, db_password, db.replace("db", ""))

使用方法: python find_bigkey.py IP PORT redis密碼,例如: python find_bigkey.py 127.0.0.1 6379 123456,執行后如圖:

3.rdb_bigkeys工具
這是用go寫的一款工具,分析rdb文件,找出文件中的大key,實測發現,不管是執行時間還是准確度都是很高的,一個3G左右的rdb文件,執行完大概兩三分鍾,直接導出到csv文件,方便查看,個人推薦使用該工具去查找大key。
工具地址: https://github.com/weiyanwei412/rdb_bigkeys
編譯方法:

mkdir /home/gocode/
export GOPATH=/home/gocode/
cd GOROOT
git clone https://github.com/weiyanwei412/rdb_bigkeys.git
cd rdb_bigkeys
go get 
go build

執行完成生成可執行文件rdb_bigkeys。
使用方法: ./rdb_bigkeys --bytes 1024 --file bigkeys.csv --sep 0 --sorted --threads 4 /home/redis/dump.rdb
/home/redis/dump.rdb修改為實際的文件路徑
上述命令分析dump.rdb文件中大於1024bytes的KEY, 由大到小排好序, 以CSV格式把結果輸出到bigkeys.csv的文件中,文件格式如圖:

每列分別為數據庫編號,key類型,key名,key大小,元素數量,最大值元素名,元素大小,key過期時間。

通過比較發現,第三種方式的數據內容更豐富,更准確,個人建議采用第三種方式。各位如果覺得還有點意義,煩請點一下推薦,加個關注,互相交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM