在 Redis 中,还有哪些其他命令可以代替 KEYS 命令,实现同样的功能呢?这些命令的复杂度会导致 Redis 变慢吗?
如果想要获取整个实例的所有key,建议使用SCAN命令代替。客户端通过执行SCAN $cursor COUNT $count可以得到一批key以及下一个游标$cursor,然后把这个$cursor当作SCAN的参数,再次执行,以此往复,直到返回的$cursor为0时,就把整个实例中的所有key遍历出来了。
关于SCAN讨论最多的问题就是,Redis在做Rehash时,会不会漏key或返回重复的key。
在使用SCAN命令时,不会漏key,但可能会得到重复的key,这主要和Redis的Rehash机制有关。Redis的所有key存在一个全局的哈希表中,如果存入的key慢慢变多,在达到一定阈值后,为了避免哈希冲突导致查询效率降低,这个哈希表会进行扩容。与之对应的,key数量逐渐变少时,这个哈希表会缩容以节省空间。
1、为什么不会漏key?Redis在SCAN遍历全局哈希表时,采用*高位进位法*的方式遍历哈希桶(可网上查询图例,一看就明白),当哈希表扩容后,通过这种算法遍历,旧哈希表中的数据映射到新哈希表,依旧会保留原来的先后顺序,这样就可以保证遍历时不会遗漏也不会重复。
2、为什么SCAN会得到重复的key?这个情况主要发生在哈希表缩容。已经遍历过的哈希桶在缩容时,会映射到新哈希表没有遍历到的位置,所以继续遍历就会对同一个key返回多次。
SCAN是遍历整个实例的所有key,另外Redis针对Hash/Set/Sorted Set也提供了HSCAN/SSCAN/ZSCAN命令,用于遍历一个key中的所有元素,建议在获取一个bigkey的所有数据时使用,避免发生阻塞风险。
但是使用HSCAN/SSCAN/ZSCAN命令,返回的元素数量与执行SCAN逻辑可能不同。执行SCAN $cursor COUNT $count时一次最多返回count个数的key,数量不会超过count。
但Hash/Set/Sorted Set元素数量比较少时,底层会采用intset/ziplist方式存储,如果以这种方式存储,在执行HSCAN/SSCAN/ZSCAN命令时,会无视count参数,直接把所有元素一次性返回,也就是说,得到的元素数量是会大于count参数的。当底层转为哈希表或跳表存储时,才会真正使用发count参数,最多返回count个元素。
redis中KEYS替代命令
最新推荐文章于 2023-11-30 21:59:16 发布