閱讀127 返回首頁    go 阿裏雲 go 技術社區[雲棲]


阿裏雲redis大key搜索工具

Redis提供了list、hash、zset等複雜類型的數據結構,業務在使用的時候可能由於key設計不合理導致某個key過大,由於redis簡單的單線程模型,業務在獲取或者刪除大key的時候都會有一定的影響,另外在集群模式下由於大key的產生還很容易導致某個子節點的內存滿,綜上所述我們需要提供大key的搜索工具。

初始化環境

安裝python客戶端

下載python客戶端
wget “https://pypi.python.org/packages/68/44/5efe9e98ad83ef5b742ce62a15bea609ed5a0d1caf35b79257ddb324031a/redis-2.10.5.tar.gz#md5=3b26c2b9703b4b56b30a1ad508e31083”

解壓安裝

tar -xvf redis-2.10.5.tar.gz
cd redis-2.10.5
sudo python setup.py install

掃描腳本

遍曆key

對於Redis主從版本可以通過scan命令進行掃描,對於集群版本提供了ISCAN命令進行掃描,命令規則如下, 其中節點個數node可以通過info命令來獲取到

ISCAN idx cursor [MATCH pattern] [COUNT count](idx為節點的id,從0開始,16到64gb的集群實例為8個節點故idx為0到7,128g 256gb的為16個節點)

掃描腳本

import sys
import redis

def check_big_key(r, k,node):
  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 > 10240:
    bigKey = True
  if bigKey :
    print db,k,type,length,node

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,0)

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,node)
      cursor = iscan[0]
      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 = r.info()['nodecount']
  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 host 6379 password來執行,支持阿裏雲Redis的主從版本和集群版本的大key查找,默認大key的閾值為10240,也就是對於string類型的value大於10240的認為是大key,對於list的話如果list長度大於10240認為是大key,對於hash的話如果field的數目大於10240認為是大key。另外默認該腳本每次搜索1000個key,對業務的影響比較低,不過最好在業務低峰期進行操作,避免scan命令對業務的影響。腳本輸出內容個數如下,最後一列為集群裏麵所在節點的序號。

check  db0   {'keys': 79648, 'expires': 0, 'avg_ttl': 0}
db0 mylist list 59819 2

最後更新:2017-07-04 17:02:26

  上一篇:go  Apache官方舉辦的第一屆HBase亞洲技術大會即將來襲!
  下一篇:go  通過 Doctype 啟用瀏覽器模式 【已翻譯100%】(2/2)