Redis KEYS命令用于查找所有符合给定模式(pattern)的key。语法:KEYS pattern,其中pattern支持*?[]等glob-style通配符。示例:KEYS * 返回所有key;KEYS user:* 返回以user:开头的key;KEYS user:9[0-9]* 返回user:90x、user:91x等key。在生产环境中慎用KEYS,因为它会阻塞服务器,时间复杂度O(N*M),N是key数量,M是pattern复杂度。高效替代:使用SCAN命令,它是非阻塞的增量迭代器,语法SCAN cursor [MATCH pattern] [COUNT count],cursor=0开始,SCAN返回下一个cursor和新key列表,直到cursor=0结束。
使用SCAN高效检索
SCAN 0 MATCH user:* COUNT 100 会返回一批匹配user:*的key,不会阻塞服务器。示例代码:while true; do cursor=$(redis-cli --scan --pattern 'user:*' | head -n1); if [ $cursor = 0 ]; break; fi; redis-cli scan $cursor MATCH user:* COUNT 100; done。这样可以安全地在大型Redis实例中检索key。SCAN还有HSCAN、SSCAN、ZSCAN变体,用于Hash、Set、ZSet的成员迭代。
键值管理技巧
1. 命名规范:使用命名空间如session:user:123、cache:article:456,避免KEYS *。2. 定期清理:用EXPIRE设置TTL,或用Redis的内存淘汰策略maxmemory-policy。3. 监控key数量:INFO keyspace显示db0:keys=xxx,expires=yyy。4. 批量操作:避免单个KEYS后循环DEL,用EVAL脚本批量删除:EVAL "for i=1,ARGV[#ARGV] do redis.call('del',KEYS[i]) end" 0 key1 key2 ...。5. 集群环境:KEYS不支持多slot,用SCAN并指定HASH槽。
实际案例
假设有百万用户key如user:1001、user:1002,想删除user:1xxx:redis-cli --scan --pattern 'user:1*' | xargs redis-cli del。这样高效删除。或用pipeline批量:redis-cli --scan --pattern 'user:1*' --pipe | redis-cli --pipe,避免网络开销。注意:生产环境先备份或用SCAN测试。
性能对比
KEYS在10万key下可能耗时0.1s,在千万key下几分钟甚至超时阻塞。SCAN每次迭代毫秒级,总时间线性但不阻塞,可随时中断。最佳实践:开发用KEYS,生产用SCAN。
FAQ
Q: KEYS命令为什么危险?
A: 它遍历整个key空间阻塞服务器,数据多时导致高延迟甚至宕机。
Q: SCAN怎么处理大key空间?
A: 分批返回,每次COUNT控制批次大小,总迭代完成所有匹配。
Q: 如何删除匹配key?
A: 用--scan --pattern配合xargs del,或Lua脚本批量DEL。
Q: Redis集群用什么代替KEYS?
A: 逐节点SCAN,或客户端分片逻辑。
Q: 还有其他迭代命令吗?
A: 是的,HSCAN/SSCAN/ZSCAN针对集合类型成员。