如何判断redis变慢了?
在实际解决问题之前,我们首先要弄清楚,如何判断 Redis 是不是真的变慢了。
最直接的方法就是查看redis的响应延迟。方法就是基于当前环境下的 Redis 基线性能做判断。所 谓的基线性能呢,也就是一个系统在低压力、无干扰下的基本性能,这个性能只由当前的软硬件配置决定。
redis-cli 命令提供了–intrinsic-latency 选项,可以用来监测和统计测试期间内的最大延迟,这个延迟可以作为 Redis 的基线性能。其中,测试时长可以用–intrinsic-latency 选项的参数来指定。
举个例子:运行下面的命令,该命令会打印 120 秒内监测到的最大延迟。可 以看到,这里的最大延迟是 119 微秒,也就是基线性能为 119 微秒。一般情况下,运行 120 秒就足够监测到最大延迟了,所以,我们可以把参数设置为 120。
./redis-cli --intrinsic-latency 120
Max latency so far: 17 microseconds.
Max latency so far: 44 microseconds.
Max latency so far: 94 microseconds.
Max latency so far: 110 microseconds.
Max latency so far: 119 microseconds.
然后把运行时延迟和基线性能进行对比,如果你观察到的 Redis 运行时延迟是其基线性能的 2 倍及以上,就可以认定 Redis 变慢了。
排查是否是网络原因
一个简单的方法是用 iPerf 这样的工具,测量从Redis 客户端到服务器端的网络延迟。如果这个延迟有几十毫秒甚至是几百毫秒,就说明,Redis 运行的网络环境中很可能有大流量的其他应用程序在运行,导致网络拥塞了。这个时候,你就需要协调网络运维,调整网络的流量分配了.
Redis 自身的操作特性、文件系统和操作系统,它们是影响 Redis 性能的三大要素.
Redis自身的操作特性
- 慢查询命令 慢查询命令,就是指在 Redis 中执行速度慢的命令,这会导致 Redis 延迟增加。Redis 提 供的命令操作很多,并不是所有命令都慢,这和命令操作的复杂度有关。所以,我们必须 要知道 Redis 的不同命令的复杂度。
当发现 Redis 性能变慢时,可以通过 Redis 日志,或者是 latency monitor 工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的慢查询命令。
如果的确有大量的慢查询命令,有几种处理方式:
- 用其他高效命令代替。比如说,如果你需要返回一个 SET 中的所有成员时,不要使用SMEMBERS 命令,而是要使用 SSCAN 多次迭代返回,避免一次返回大量数据,造成线程阻塞。
- 当你需要执行排序、交集、并集操作时,可以在客户端完成,而不要用 SORT、SUNION、SINTER 这些命令,以免拖慢 Redis 实例。
- 如果有条件,则换更好的CPU。
提示:KEYS 命令需要遍历存储的键值对,所以操作延时高。如果你不了解它的实现而使用 了它,就会导致 Redis 性能变慢。所以,KEYS 命令一般不被建议用于生产环境中。
- 过期key操作 Redis 键值对的 key 可以设置过期时间。默认情况下,Redis 每 100 毫秒会删除一些过期key,具体的算法如下:
- 采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 个数的 key,并将其中过期的key 全部删除;
- 如果超过 25% 的 key 过期了,则重复删除的过程,直到过期 key 的比例降至 25% 以下。
而删除操作是阻塞的(Redis 4.0 后可以用异步线程机制来减少阻塞影响),一旦算法的第二个条件触发,Redis 的线程就会一直执行删除,这样一来,就没办法正常服务其他的键值操作了,就会进一步引起其他键值操作的延迟增加,Redis 就会变慢。
那么,算法的第二条是怎么被触发的呢?其中一个重要来源,就是频繁使用带有相同时间 参数的 EXPIREAT 命令设置过期 key,这就会导致,在同一秒内有大量的 key 同时过期。
AOF同步写、AOF日志重写
对于 always 策略来说,Redis 需要确保每个操作记录日志都写回磁盘,就需要调用fsync命令,而该操作是比较耗时的。
AOF 重写会对磁盘进行大量 IO 操作,同时,fsync 又需要等到数据写到磁盘后才能返回,所以,当 AOF 重写的压力比较大时,就会导致 fsync 被阻塞。虽然 fsync 是由后台子线程负责执行的,但是,主线程会监控 fsync 的执行进度。
当主线程使用后台子线程执行了一次 fsync,需要再次把新接收的操作记录写回磁盘时,如果主线程发现上一次的 fsync 还没有执行完,那么它就会阻塞。所以,如果后台子线程执行的 fsync 频繁阻塞的话(比如 AOF 重写占用了大量的磁盘 IO 带宽),主线程也会阻塞,导致 Redis 性能变慢。
操作系统的内存swap
内存 swap 是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制,涉及到磁盘的读写,所以,一旦触发 swap,无论是被换入数据的进程,还是被换出数据的进程,其性能都会受到慢速磁盘读写的影响。
Redis 是内存数据库,内存使用量大,如果没有控制好内存的使用量,或者和其他内存需求大的应用一起运行了,就可能受到 swap 的影响,而导致性能变慢。