Redis20:keys、scan、bigkeys、查看key的存储方式
keys、scan、bigkeys、查看key的存储方式
keys
keys 正则表达式 来找到所有符合要求的key,但是这个指令有几个缺点,首先就是没有限制参数,可能查出超多的数据,还有就是它是遍历算法,复杂度是ON,因为redis是单线程,如果数据多的话会导致redis卡顿。
所以代替keys 指令的就是新的指令:scan
scan
它有一些特点:
1、复杂度也是ON。但是他是游标分步进行的,不会阻塞线程。
2、提供limit参数,可以模糊的控制返回的最大条数
3、游标的唯一状态就是命令的返回值
4、遍历的结果可能用重复
5、遍历过程中的数据修改可能不会被遍历到
使用:
scan 0 match 正则表达式 count 1000
此时会返回一个数:游标的状态和一个集合
然后把游标的状态取出放到第二个位置的参数再次执行,直至返回状态为0,返回空集合不代表遍历结束。
scan指令的第一个参数代表一维数组的位置索引,最后一个参数代表此次访问的槽数
(redis内部全部数据都存在一个巨大的字典中,数组加链表)
scan不是从第1个位置遍历到最后一个位置,而是用高位进位加法来选择遍历顺序,这是因为这样的顺序可以在字典的扩容缩容时避免重复和遗漏。
字典在扩容时会扩容到现在大小的两倍,如果8位扩容到16位,对于原来在槽位3的会分大约一半到槽位11,这个顺序正是遍历顺序,可以保证即使扩容了也不会重复遍历,如果缩容的话会进行一些重复遍历,因为原来多个位置的数据现在合并到了一起。
这个扩容缩容会有rehash,java是非渐进式的,redis用的是渐进式的rehash,同时保留新旧数组,在后续的定时任务中慢慢转移,scan命令同时在新旧数组中查找。
大key的查找
如果单个key过大,给集群数据的迁移造成了很大的困难,扩容缩容时也是。大key是redis卡顿最常见的原因,有一个指令可以找到大key:
redis-cll –h 127.0.0.1 –p 701 –bigkeys
还可以加休眠参数,避免占用资源过多。
查看key的存储方式
用debug object key可以观察对应key的属性,其中encoding是它的存储方式,存储编码方式不同,不同类型的数据结构采用的存储位数不同。