共计 870 个字符,预计需要花费 3 分钟才能阅读完成。
最近在公司对 redis 做一些二次开发时,发现一个 randomkey 命令可能导致整个 redis 实例长时间阻塞的问题,redis 版本为 3.2.9,以此记录。
问题
因为咱们公司应用的是 redis 集群版 Codis,Codis 内置的 redis 版本比拟低,为 3.2.9 版本。
咱们近期在做 Codis 双机房时,须要对 redis 减少一些性能以此反对双机房,在开发和测试中发现,执行 randomkey 命令有可能导致整个 redis 长时间阻塞的问题。
randomkey 次要性能是在 redis 中随机返回一个 key 进去,它随机选取 key 的代码如下。
从下面代码能够看进去,如果以后是个 slave,并且整个实例中存在大量曾经过期的 key(key 已过期,但 redis 还未来得及删除 key),执行 randomkey 命令时,因为找不到不过期的 key,那么这个逻辑就会陷入死循环,阻塞住整个实例,整个实例不可用。
如果以后是 master,执行 randomkey 命令时,redis 会始终随机抉择 key,直到找到一个不过期的 key,同时会把曾经过期的 key 从整个实例中删除。
也就是说,在这种场景下,尽管不会长时间阻塞整个实例,但也会比执行一个一般的命令耗时要久。如果你在一个大量已过期的实例上执行 randomkey 命令,那可能会导致业务拜访 redis 变慢。
解决
咱们比照了官网最新版的 redis,曾经针对此问题进行了修复。
解决方案就是减少一个最大重试次数,如果整个实例都是过期 key,那么最多寻找 maxtries 次就返回,防止阻塞整个实例。
留神点
但要留神的是,如果达到了 maxtries,那么返回的 key 是曾经过期的 key,你尽管在 randomkey 中看到了这个 key,但对这个 key 执行其余命令时,还是拿不到这个 key 的。
这个计划只针对 slave 上执行这个命令进行了修复,也就是不会再让 redis 陷入死循环。
但在 master 上执行这个命令还是会产生上述的变慢问题,如果你在应用 redis 时,常常应用这个命令,同时实例中存在大量曾经过期的 key,那么 redis 变慢很有可能是这个问题导致的。