什么是大key
查询bigkey
集群模式查看bigkey
redis-cli排查
cluster模式排查大key
因为clister集群模式下查询bigkey时,因为键会分散在不同的槽(slot)和不同的节点上,因此需要分别连到各个主节点进行检查,或者在命令添加-c参数
首先需要查看cluster各个节点,连接其中任意一个节点执行以下命令
CLISTER NODES
查看集群中每个节点的信息,返回结果如下,是以空格分割的CSV格式
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,hostname4 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,hostname2 master - 0 1426238316232 2 connected 5461-10922
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,hostname3 master - 0 1426238318243 3 connected 10923-16383
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,hostname5 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,hostname6 slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,hostname1 myself,master - 0 0 1 connected 0-5460
每行格式如下:
<id> <ip:port@cport[,hostname]> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>
其中
master 主节点
slave 从节点
myself 当前节点
fail 当前节点处于失恋状态
以三主三从为例可以看到当前集群的节点信息
通过以上获取到各个节点信息,可以查看每个节点的bigkey情况
执行命令
redis-cli -h 节点ip -p 端口 --bigkeys
返回的并非就是bigkey, 而是每个类型的top1,同时给出每种数据类型的键值个数和平均大小, 大致衡量大小为:string类型大于10kb,hash,zset,list,set元素个数超过5000个,
以三主三从为例,如果卡槽为0-5460、5461-10922可能会出现以下提示
意味着访问的key被移到另一卡槽了可以手动重定向到提示的MOVE节点进行尝试
除了上述方法,也可以使用下面命令查看某个key的大小
MEMORY USAGE key [SAMPLES count]
返回结果为所占字节大小,如果key不存在resps2返回nil,resp3返回null
解决方案
如何是key的名称较大,可以使用md5进行摘要算法生成固定的长度
如果是value较大,可以拆分为多个子key,比如一个大的list,拆分成多个小的list
再利用管道操作可以一定程度上保证事务
public void saveBigKey() {
ArrayList<Object> list = new ArrayList<>();
List<List<Object>> partList = Lists.partition(list, 100);
String masterKey = "master_key";
redisTemplate.executePipelined((RedisCallback<Object>) con -> {
con.del(rawKey(masterKey));
for (int i = 0; i < partList.size(); i++) {
String partKey = String.format("CHILD_KEY_%s", i);
con.set(rawKey(partKey), rawValue(JsonUtil.dumpObject(partList.get(i))));
con.expire(rawKey(partKey), TimeUnit.DAYS.toSeconds(2));
con.zAdd(rawKey(masterKey), i, rawValue(partKey));
}
con.expire(rawKey(masterKey), TimeUnit.DAYS.toSeconds(1));
return null;
});
}
RedisSerializer keySerializer() {
return redisTemplate.getKeySerializer();
}
RedisSerializer valueSerializer() {
return redisTemplate.getValueSerializer();
}
@SuppressWarnings("unchecked")
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if (keySerializer() == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer().serialize(key);
}
@SuppressWarnings("unchecked")
byte[] rawValue(Object value) {
if (valueSerializer() == null && value instanceof byte[]) {
return (byte[]) value;
}
return valueSerializer().serialize(value);
}
标签:return,解决方案,Redis,bigkey,key,byte,节点,con
From: https://www.cnblogs.com/LiuFqiang/p/18100719