redis使用scan模糊匹配key
redis使用scan模糊匹配key
在redis实际使用中,会遇到一个问题:如何从海量的key中找出满足特定前缀的key列表?
1.不要使用keys*
redis提供了一个简单包里的指令keys用来列出所有满足特定正则字符串规则的key。
keys xxx*
这个指令有致命的弊端,在实际环境中最好不要使用:
这个指令没有offset、limit参数,是要一次性吐出所有满足条件的key,由于redis是单线程的,其所有操作都是原子的,而 keys 算法是遍历算法,复杂度是 O(n),如果实例中有千万级以上的 key,这个指令就会导致 Redis 服务卡顿,所有读写 Redis 的其它的指令都会被延后甚至会超时报错,可能会引起缓存雪崩甚至数据库宕机。
我们可以通过配置设置禁用这些命令,在 redis.conf 中,在 SECURITY 这一项中,我们新增以下命令:
rename-command flushall ""
rename-command flushdb ""
rename-command config ""
rename-command keys ""
另外,对于FLUSHALL命令,需要设置配置文件中appendonly no,否则服务器是无法启动。
Redis 为了解决这个问题,它在 2.8 版本中加入了scan
。scan 相比 keys 具备有以下特点:
- 复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;
- 提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hint,返回的结果可多可少;
- 同 keys 一样,它也提供模式匹配功能;
- 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;
- 返回的结果可能会有重复,需要客户端去重复,这点非常重要;
- 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
- 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;
2.scan使用
SCAN 命令及其相关的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代:
SCAN命令用于迭代当前数据库中的数据库键。
SSCAN命令用于迭代集合键中的元素。
HSCAN命令用于迭代哈希键中的键值对。
ZSCAN命令用于迭代有序集合中的元素(包括元素成员和元素分值)
相比于keys命令,SCAN命令有两个比较明显的优势:
1)SCAN命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程。
2)SCAN命令提供了count参数,可以控制每次遍历的集合数。
可以理解为SCAN是渐进式的keys
Scan命令语法如下:
SCAN cursor [MATCH pattern] [COUNT count]
curson-游标
pattern-匹配的模式
count-指定每次遍历多少个集合
SCAN命令是基于游标的,每次调用后,都会返回一个游标,用于下一次迭代。
第一次 Scan 时指定游标为 0,表示开启新的一轮迭代,然后 Scan 命令返回一个新的游标,作为第二次 Scan 时的游标值继续迭代,一直到 Scan 返回游标为0,表示本轮迭代结束。
Scan完成一次迭代,需要和redis进行多次交互。
3.scan参数
Scan 命令中的 Count 指定一次扫描多少 Key,这里指定为 1000,几百万Key就需要几千次迭代,即和 Redis 交互几千次,然后因为是远程连接,网络延迟比较大,所以耗时特别长。
将 Count 参数调大后,减少了交互次数,会好很多。Count 参数越大,Redis 阻塞时间也会越长,需要取舍。
更多推荐
所有评论(0)