社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
redis的"慢查询"与redis定义慢查询的时间阈值有关,Redis提供了slowlog-log-slower-than和slowlog-max-len两个配置,slowlog-log-slower-than指当redis命令的执行时间超过该值时,redis会将其记录在redis的慢查询日志中,slowlog-max-len表示记录的条数(超过时会只存储最新的slowlog-max-len条),slowlog-log-slower-than的默认值为10000us,也就是一般来说,redis命令执行时间超过10ms时,我们认为产生了慢查询,redis慢查询日志记录的是执行时间,没有慢查询,并不表示客户端没有超时问题,有可能网络传输有延迟,也有可能排队的命令比较多,导致redis查询也很慢。
在业务使用过程中,我们发现redis使用上出现慢查询的原因有主要以下几种:
针对上述的原因,下面逐个给出导致慢查询的原因细节,并提出对应解决redis慢查询的有效方法。
负责的命令一般指O(N)以上的命令,比如sort、sunion、zunionstore聚合类的命令,或是O(N)类的命令,但是N的值由于业务原因特别大。
对于O(N)以上的命令,redis在操作内存数据时,耗时过高,会耗费更多的cpu资源,导致查询变慢。对于O(N)类的命令,由于N的值特别大Redis 一次需要返回给客户端的数据过多,更多时间花费在数据协议的组装和网络传输过程中。
除此之外,我们都知道,Redis 是单线程处理客户端请求的,如果你经常使用以上命令,那么当 Redis 处理客户端请求时,一旦前面某个命令发生耗时,就会导致后面的请求发生排队,对于客户端来说,响应延迟也会长。
针对此类原因,我们一般有以下两个原则:
所谓大key问题其实并不是值key过大,实则值key对应的value的值过大,此类问题在SET / DEL这类命令中也常出现慢查询。
首先我们要了解下redis写入与删除数据做了什么:
顺边提下检测大key的一个命令:
redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01
输出结果会展示每种数据类型所占用的最大内存 / 拥有最多元素的 key 是哪一个,以及每种数据类型在整个实例中的占比和平均大小 / 元素数量。
其实,使用这个命令的原理,就是 Redis 在内部执行了 SCAN 命令,遍历整个实例中所有的 key,然后针对 key 的类型,分别执行 STRLEN、LLEN、HLEN、SCARD、ZCARD 命令,来获取 String 类型的长度、容器类型(List、Hash、Set、ZSet)的元素个数。
这里我需要提醒你的是,当执行这个命令时,要注意 2 个问题:
集中过期产生的慢查询很容易被忽略,可能我们在业务上线时,并没有发生慢查询,而是业务运行时在某个时间点总是突然发生慢查询。为什么集中过期会导致慢查询呢?我们首先了解下redis的两种过期策略:
值得注意的是,主动过期key的定时任务是在redis主线程种执行的,也就是说如果在执行主动过期的过程中,出现了集中过期,那就需要大量删除过期 key ,那么此时应用程序在访问 Redis 时,必须要等待这个过期任务执行结束,Redis 才可以服务这个客户端请求,此时应用访问 Redis 就可能产生查询。
如果此时需要过期删除的是一个 bigkey,那么这个耗时会更久。而且,这个操作延迟的命令并不会记录在慢日志中。
因为慢日志中只记录一个命令真正操作内存数据的耗时,而 Redis 主动删除过期 key 的逻辑,是在命令真正执行之前执行的。
对于集中过期问题,有以下建议
本文介绍了redis慢查询的含义,列举了业务使用种常导致redis慢查询的几个原因以及对应的解决办法,希望大家有所收获。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!