「生产上不要用 KEYS」几乎是 Redis 的第一条军规。它到底有多危险?危险与什么有关?这篇在 10 万到 300 万个 key 的库上量 KEYS 的阻塞时间,对比 SCAN,并演示怎么从权限上直接禁掉它。
key 总数 KEYS * 命令耗时 ms PING 最大停顿 ms KEYS nomatch* 耗时 ms PING 最大停顿 ms
100000 70 30.9 4 4.3
500000 339 52.4 23 22.0
1000000 702 123.1 43 41.8
3000000 2181 424.5 185 185.2停顿随 key 数近似线性增长:10 万个 key 31 ms、100 万个 123 ms、300 万个 424 ms。对没有匹配的模式,命令耗时和停顿都小很多(185 ms @ 300 万),因为不用构造大回复——但遍历部分的开销没有免除:危险与「key 总数」有关,与「匹配了多少」关系不大。
3000000 个 key:SCAN 遍历总耗时 2658 ms(2998 次调用),期间另一个连接 PING 最大停顿 1.89 ms
SCAN COUNT 1000 遍历 300 万个 key,2998 次调用共 2658 ms,期间 PING 最大停顿 1.89 ms。总耗时和 KEYS 一个量级,但每次只占主线程很短一段。
> KEYS * (error) NOPERM User app has no permissions to run the 'keys' command > GET key:1 "v"
ACL 可以把 keys 从某个用户的权限里去掉:该用户执行 KEYS 得到 NOPERM,其它命令不受影响。ACL 的细节见第 122–125 篇。