如何判断redis慢了
来自
https://mp.weixin.qq.com/s?__biz=MzIzOTU0NTQ0MA==&mid=2247532967&idx=1&sn=19790c981aa33502aa1e3a8abe9cd064&chksm=e92a7ca8de5df5befc6cc534cbabdb847eff41d0b7cef373191e49df38211e74f8064bd5b62f&from=industrynews&version=4.1.3.6112&platform=win#rd
一、Redis变慢了排查步骤
1、获取 Redis 实例在当前环境下的基线性能。
2、是否用了慢查询命令?如果是的话,就使用其他命令替代慢查询命令,或者把聚合计算命令放在客户端做。
3、是否对过期 key 设置了相同的过期时间?对于批量删除的 key,可以在每个 key 的过期时间上加一个随机数,避免同时删除。
4、是否存在 bigkey?对于 bigkey 的删除操作,如果你的 Redis 是 4.0 及以上的版本,可以直接利用异步线程机制减少主线程阻塞;如果是 Redis 4.0 以前的版本,可以使用 SCAN 命令迭代删除;对于 bigkey 的集合查询和聚合操作,可以使用 SCAN 命令在客户端完成。
5、Redis AOF 配置级别是什么?业务层面是否的确需要这一可靠性级别?如果我们需要高性能,同时也允许数据丢失,可以将配置项 no-appendfsync-on-rewrite 设置为 yes,避免 AOF 重写和 fsync 竞争磁盘 IO 资源,导致 Redis 延迟增加。当然, 如果既需要高性能又需要高可靠性,最好使用高速固态盘作为 AOF 日志的写入盘。
6、Redis 实例的内存使用是否过大?发生 swap 了吗?如果是的话,就增加机器内存,或者是使用 Redis 集群,分摊单机 Redis 的键值对数量和内存压力。同时,要避免出现 Redis 和其他内存需求大的应用共享机器的情况。
7、在 Redis 实例的运行环境中,是否启用了透明大页机制?如果是的话,直接关闭内存大页机制就行了。
8、是否运行了 Redis 主从集群?如果是的话,把主库实例的数据量大小控制在 2~4GB,以免主从复制时,从库因加载大的 RDB 文件而阻塞。
9、是否使用了多核 CPU 或 NUMA 架构的机器运行 Redis 实例?使用多核 CPU 时,可以给 Redis 实例绑定物理核;使用 NUMA 架构时,注意把 Redis 实例和网络中断处理程序运行在同一个 CPU Socket 上。
二、Redis为什么变慢了
1.Redis真的变慢了吗?
对 Redis 进行基准性能测试例如,我的机器配置比较低,当延迟为 2ms 时,我就认为 Redis 变慢了,但是如果你的硬件配置比较高,那么在你的运行环境下,可能延迟是 0.5ms 时就可以认为 Redis 变慢了。所以,你只有了解了你的 Redis 在生产环境服务器上的基准性能,才能进一步评估,当其延迟达到什么程度时,才认为 Redis 确实变慢了。为了避免业务服务器到 Redis 服务器之间的网络延迟,你需要直接在 Redis 服务器上测试实例的响应延迟情况。执行以下命令,就可以测试出这个实例 60 秒内的最大响应延迟:
./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. 36481658 total runs (avg latency: 3.2893 microseconds / 3289.32 nanoseconds per run). Worst run took 36x longer than the average latency.
从输出结果可以看到,这 60 秒内的最大响应延迟为 119 微秒(0.119毫秒)。你还可以使用以下命令,查看一段时间内 Redis 的最小、最大、平均访问延迟
$ redis-cli -h 127.0.0.1 -p 6379 --latency-history -i 1 min: 0, max: 1, avg: 0.13 (100 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.12 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.10 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (98 samples) -- 1.00 seconds range min: 0, max: 1, avg: 0.08 (99 samples) -- 1.01 seconds range
如果你观察到的 Redis 运行时延迟是其基线性能的 2 倍及以上,就可以认定 Redis 变慢了。
网络对 Redis 性能的影响,一个简单的方法是用 iPerf 这样的工具测试网络极限带宽。
服务器端 # iperf -s -p 12345 -i 1 -M iperf: option requires an argument -- M ------------------------------------------------------------ Server listening on TCP port 12345 TCP window size: 4.00 MByte (default) ------------------------------------------------------------ [ 4] local 172.20.0.113 port 12345 connected with 172.20.0.114 port 56796 [ ID] Interval Transfer Bandwidth [ 4] 0.0- 1.0 sec 614 MBytes 5.15 Gbits/sec [ 4] 1.0- 2.0 sec 622 MBytes 5.21 Gbits/sec [ 4] 2.0- 3.0 sec 647 MBytes 5.42 Gbits/sec [ 4] 3.0- 4.0 sec 644 MBytes 5.40 Gbits/sec [ 4] 4.0- 5.0 sec 651 MBytes 5.46 Gbits/sec [ 4] 5.0- 6.0 sec 652 MBytes 5.47 Gbits/sec [ 4] 6.0- 7.0 sec 669 MBytes 5.61 Gbits/sec [ 4] 7.0- 8.0 sec 670 MBytes 5.62 Gbits/sec [ 4] 8.0- 9.0 sec 667 MBytes 5.59 Gbits/sec [ 4] 9.0-10.0 sec 667 MBytes 5.60 Gbits/sec [ 4] 0.0-10.0 sec 6.35 GBytes 5.45 Gbits/sec 客户端 # iperf -c 服务器端IP -p 12345 -i 1 -t 10 -w 20K ------------------------------------------------------------ Client connecting to 172.20.0.113, TCP port 12345 TCP window size: 40.0 KByte (WARNING: requested 20.0 KByte) ------------------------------------------------------------ [ 3] local 172.20.0.114 port 56796 connected with 172.20.0.113 port 12345 [ ID] Interval Transfer Bandwidth [ 3] 0.0- 1.0 sec 614 MBytes 5.15 Gbits/sec [ 3] 1.0- 2.0 sec 622 MBytes 5.21 Gbits/sec [ 3] 2.0- 3.0 sec 646 MBytes 5.42 Gbits/sec [ 3] 3.0- 4.0 sec 644 MBytes 5.40 Gbits/sec [ 3] 4.0- 5.0 sec 651 MBytes 5.46 Gbits/sec [ 3] 5.0- 6.0 sec 652 MBytes 5.47 Gbits/sec [ 3] 6.0- 7.0 sec 669 MBytes 5.61 Gbits/sec [ 3] 7.0- 8.0 sec 670 MBytes 5.62 Gbits/sec [ 3] 8.0- 9.0 sec 667 MBytes 5.59 Gbits/sec [ 3] 9.0-10.0 sec 668 MBytes 5.60 Gbits/sec [ 3] 0.0-10.0 sec 6.35 GBytes 5.45 Gbits/sec
2.使用复杂度过高的命令
首先,第一步,你需要去查看一下 Redis 的慢日志(slowlog)。Redis 提供了慢日志命令的统计功能,它记录了有哪些命令在执行时耗时比较久。查看 Redis 慢日志之前,你需要设置慢日志的阈值。例如,设置慢日志的阈值为 5 毫秒,并且保留最近 500 条慢日志记录:
# 命令执行耗时超过 5 毫秒,记录慢日志 CONFIG SET slowlog-log-slower-than 5000 # 只保留最近 500 条慢日志 CONFIG SET slowlog-max-len 500
1.经常使用 O(N) 以上复杂度的命令,例如 SORT、SUNION、ZUNIONSTORE 聚合类命令2.使用 O(N) 复杂度的命令,但 N 的值非常大第一种情况导致变慢的原因在于,Redis 在操作内存数据时,时间复杂度过高,要花费更多的 CPU 资源。第二种情况导致变慢的原因在于,Redis 一次需要返回给客户端的数据过多,更多时间花费在数据协议的组装和网络传输过程中。另外,我们还可以从资源使用率层面来分析,如果你的应用程序操作 Redis 的 OPS 不是很大,但 Redis 实例的 CPU 使用率却很高,那么很有可能是使用了复杂度过高的命令导致的。
3.操作bigkey
如果你查询慢日志发现,并不是复杂度过高的命令导致的,而都是 SET / DEL 这种简单命令出现在慢日志中,那么你就要怀疑你的实例否写入了 bigkey。
redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 1 -------- summary ------- Sampled 829675 keys in the keyspace! Total key length in bytes is 10059825 (avg len 12.13) Biggest string found 'key:291880' has 10 bytes Biggest list found 'mylist:004' has 40 items Biggest set found 'myset:2386' has 38 members Biggest hash found 'myhash:3574' has 37 fields Biggest zset found 'myzset:2704' has 42 members 36313 strings with 363130 bytes (04.38% of keys, avg size 10.00) 787393 lists with 896540 items (94.90% of keys, avg size 1.14) 1994 sets with 40052 members (00.24% of keys, avg size 20.09) 1990 hashs with 39632 fields (00.24% of keys, avg size 19.92) 1985 zsets with 39750 members (00.24% of keys, avg size 20.03)
这里我需要提醒你的是,当执行这个命令时,要注意 2 个问题:
1.对线上实例进行 bigkey 扫描时,Redis 的 OPS 会突增,为了降低扫描过程中对 Redis 的影响,最好控制一下扫描的频率,指定 -i 参数即可,它表示扫描过程中每次扫描后休息的时间间隔,单位是秒
2.扫描结果中,对于容器类型(List、Hash、Set、ZSet)的 key,只能扫描出元素最多的 key。但一个 key 的元素多,不一定表示占用内存也多,你还需要根据业务情况,进一步评估内存占用情况。