最近在公司对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变慢很有可能是这个问题导致的。