redis 大键查看方法汇总
前言
在操作Redis时,提示“内存不足org.redisson.client.RedisOutOfMemoryException: command not allowed when used memory > ‘maxmemory’.”。说明当前redis的某个节点内存使用超限!!
本文重点介绍 如何查看大键的分布。
一、key是如何分布的
1、集群版Redis是分片(db节点)部署的,每个db节点会分配一定数量的哈希槽(集群版redis内置16384个哈希槽)。存储key的时候,首先根据CRC16算法得出一个值,并对16384取模,取模结果即是该key需要落的slot位置,根据slot所属db节点来存储key;
2、每个db节点都有最大内存限制(maxmemory),当某个db的节点内存使用达到上限,会执行相应的内存逐出策略。
二、查看big key
1.使用redis自带–bigkeys命令
redis-cli -h xxxx -p xxxx -a "passwd" -–bigkeys
说明:
1)该方法只能查看每种数据类型最大的key;
2)生产环境需要用户侧执行,建议业务低峰期操作
2.使用python脚本查看
#python find_bigkey.py hostxxx 6379 $password
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 > 10240:
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 = 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", ""))
该方法支持阿里云Redis的主从版本和集群版本的大key查找,默认大key的阈值为10240,也就是对于string类型的value大于10240的认为是大key,对于list的话如果list长度大于10240认为是大key,对于hash的话如果field的数目大于10240认为是大key。另外默认该脚本每次搜索1000个key,对业务的影响比较低,不过最好在业务低峰期进行操作,避免scan命令对业务的影响。
参考:https://developer.aliyun.com/article/117042
3.解析redis的rdb文件
该方法是使用rdbtools工具将redis的rdb文件解析成csv文件,再直接分析csv或导入mysql后分析。
# rdb -c memory /wjqdata/redis/rdb/dump.rdb --bytes 128 -f /wjqdata/redis/rdb/test.csv
# cat test.csv | awk -F',' '{print $4,$2,$3,$1}' | sort -nr | head -50 //对键值大小进行排序
参考:https://www.cnblogs.com/cheyunhua/p/10598181.html
总结
优化big key的原则就是string减少字符串长度,list、hash、set、zset等减少成员数