Redis的KEYS 命令千万不能乱用

KESY 命令

时间复杂度: O(N) , 假设Redis中的键名和给定的模式的长度有限的情况下,N为数据库中key的个数。

Redis Keys 命令用于查找所有符合给定模式 pattern 的 key

尽管这个操作的时间复杂度是 O(N), 但是常量时间相当低。例如,在一个普通笔记本上跑Redis,扫描100万个key只要40毫秒。

命令格式 KEYS pattern

Warning: 生产环境使用 KEYS 命令需要非常小心。在大的数据库上执行命令会影响性能。这个命令适合用来调试和特殊操作,像改变键空间keyspace布局。不要在你的代码中使用 KEYS 。如果你需要一个寻找键空间中的key子集,考虑使用SCAN 或 集合结构sets。

支持的匹配模式 patterns:

  • h?llo 匹配 hello, hallo 和 hxllo
  • h*llo 匹配 hllo 和 heeeello
  • h[ae]llo 匹配 hello 和 hallo, 不匹配 hillo
  • h[^e]llo 匹配 hallo, hbllo, … 不匹配 hello
  • h[a-b]llo 匹配 hallo 和 hbllo

使用 \ 转义你想匹配的特殊字符。

背景

1、Redis是单线程的,其所有操作都是原子的,不会因并发产生数据异常

2、使用高耗时的Redis命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢

场景

在生产环境中执行 KEYS 命令的时,因为Redis是单线程的,KEYS 命令的性能随着数据库数据的增多而越来越慢,使用 KEYS 命令时会占用唯一的一个线程的大量处理时间,引发Redis阻塞并且增加Redis的CPU占用,导致所有的请求都被拖慢,可能造成Redis所在的服务器宕机,情况是很恶劣的,在实际生产运用的过程中请忽略掉。试想如果Redis阻塞超过10秒,如果有集群的场景,可能导致集群判断Redis已经故障,从而进行故障切换。

如果所有的线程在Redis那取不到数据,情况严重时可能会导致应用程序出现雪崩的情况,一瞬间全去数据库取数据,数据库就宕机了。

其他危险命令

但凡发现时间复杂度为O(N)的命令,都要慎重,不要在生产上随便使用。例如hgetall、lrange、smembers、zrange、sinter等命令,它们并非不能使用,但这些命令的时间复杂度都为O(N),使用这些命令需要明确N的值,否则也会出现缓存宕机。

1、flushdb 命令用于清空当前数据库中的所有 key

2、flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )

3、config 客户端连接后可配置服务器

如何禁用危险命令

在redis.conf中,在SECURITY这一项中,新增以下配置禁用指定命令:

rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG ""
rename-command KEYS ""

另外,对于flushall命令,需要设置配置文件中appendonly no,否则服务器是无法启动。

如果想要保留命令,但是不轻易使用,可以重命名命令来设定:

rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

TIP:更改记录到AOF文件或传输到从属服务器的命令的名称可能会导致问题。

改良建议

一、如果有这种需求的话可以自己对键值做索引,比如把各种键值存到不同的set里面,分类建立索引,这样就可以很快的得到数据,但是这样也存在一个明显的缺点,就是浪费宝贵的空间,所以还是要合理考虑,当然也可以想办法,比如对于有规律的键值,可以存储他们的始末值等等。

二、针对改良keys和smembers命令也可以使用scan命令

SCAN 命令

Redis从2.8版本开始支持scan命令,可以用来分批次扫描Redis记录,这样肯定会导致整个查询消耗的总时间变大,影响服务使用,但不会影响redis服务卡顿,SCAN命令的基本用法如下:

命令格式 SCAN cursor [MATCH pattern] [COUNT count]

SCAN 命令提供三个参数,第一个是cursor(游标),第二个是要匹配的正则,第三个是单次遍历的槽位

SCAN 命令及其相关的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(incrementally iterate)一集元素(a collection of elements):

  • SCAN 命令用于迭代当前数据库中的数据库键。
  • SSCAN 命令用于迭代集合键中的元素。
  • HSCAN 命令用于迭代哈希键中的键值对。

    Redis的KEYS 命令千万不能乱用

扫一扫手机访问