大数据量的Redis数据库为什么不能用KEYS命令

Redis, 数据库 ,

答案

因为KEYS有了能一次性遍历并返回所有的键值对,对于数据量大的Redis数据库,这个命令就会直接阻塞其他命令。

替代方案是:用SCAN命令。

解析

众所周知,Redis 是单线程程序,是按照顺序执行指令的。

如果说我们现在正在执行 keys 命令,那么其它指令必须等到当前的 keys 指令执行完了才可以继续,

再加上 keys 操作是遍历算法,复杂度是 O (n),当实例中数据量过大的时候,Redis 服务可能会卡顿,其余指令可能会延时甚至超时报错….

再者 keys 中没有 offset、limit 参数,如果说满足查询条件的 keys 特别多,那就有点尴尬了,哈哈。

所以说官方的建议是:生产环境屏蔽掉 keys 命令。

为了解决这个问题,Redis在 2.8 版本中加入了指令:scan命令:

scan - cursor [MATCH pattern] [COUNT count]

用于迭代当前数据库中的数据库键。

相比 keys ,我们来看一下 scan 的特点:

  • 复杂度虽然也是 O (n),但是它是通过游标分步进行的,不会阻塞线程;
  • 提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是对增量式迭代命令的一种提示 (hint),返回的结果可多可少;
  • keys 一样,它也提供模式匹配功能;
  • 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;
  • 返回的结果可能会有重复,需要客户端去重复,这点非常重要;
  • 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
  • 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零