Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文

微信搜索关注「水滴与银弹」公众号,第一时间获取优质技术干货。7年资深后端研发,用简单的方式把技术讲清楚。

Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右。但也正因此如此,当我们在使用 Redis 时,如果发现操作延迟变大的情况,就会与我们的预期不符。

你也许或多或少地,也遇到过以下这些场景:

  • 在 Redis 上执行同样的命令,为什么有时响应很快,有时却很慢?
  • 为什么 Redis 执行 SET、DEL 命令耗时也很久?
  • 为什么我的 Redis 突然慢了一波,之后又恢复正常了?
  • 为什么我的 Redis 稳定运行了很久,突然从某个时间点开始变慢了?

如果你并不清楚 Redis 内部的实现原理,那么在排查这种延迟问题时就会一头雾水。

如果你也遇到了以上情况,那么,这篇文章将会给你一个「全面」的问题排查思路,并且针对这些导致变慢的场景,我还会给你一个高效的解决方案。

在正文开始之前,我需要提醒你的是,这篇文章很长,涵盖的 Redis 知识点也非常广,全篇文章接近 2W 字,如果此时你的阅读环境不适合专注阅读,我建议你先收藏此文章,然后在合适的时间专注阅读这篇文章。

如果你能耐心且认真地读完这篇文章,我可以保证,你对 Redis 的性能调优将会有非常大的收获。

如果你准备好了,那就跟着我的思路开始吧!
在这里插入图片描述

Redis真的变慢了吗?

首先,在开始之前,你需要弄清楚 Redis 是否真的变慢了?

如果你发现你的业务服务 API 响应延迟变长,首先你需要先排查服务内部,究竟是哪个环节拖慢了整个服务。

比较高效的做法是,在服务内部集成链路追踪,也就是在服务访问外部依赖的出入口,记录下每次请求外部依赖的响应延时。
在这里插入图片描述
如果你发现确实是操作 Redis 的这条链路耗时变长了,那么此刻你需要把焦点关注在业务服务到 Redis 这条链路上。

从你的业务服务到 Redis 这条链路变慢的原因可能也有 2 个:

  1. 业务服务器到 Redis 服务器之间的网络存在问题,例如网络线路质量不佳,网络数据包在传输时存在延迟、丢包等情况
  2. Redis 本身存在问题,需要进一步排查是什么原因导致 Redis 变慢

通常来说,第一种情况发生的概率比较小,如果是服务器之间网络存在问题,那部署在这台业务服务器上的所有服务都会发生网络延迟的情况,此时你需要联系网络运维同事,让其协助解决网络问题。

我们这篇文章,重点关注的是第二种情况。

也就是从 Redis 角度来排查,是否存在导致变慢的场景,以及都有哪些因素会导致 Redis 的延迟增加,然后针对性地进行优化。

排除网络原因,如何确认你的 Redis 是否真的变慢了?

首先,你需要对 Redis 进行基准性能测试,了解你的 Redis 在生产环境服务器上的基准性能。

什么是基准性能?

简单来讲,基准性能就是指 Redis 在一台负载正常的机器上,其最大的响应延迟和平均响应延迟分别是怎样的?

为什么要测试基准性能?我参考别人提供的响应延迟,判断自己的 Redis 是否变慢不行吗?

答案是否定的。

因为 Redis 在不同的软硬件环境下,它的性能是各不相同的。

例如,我的机器配置比较低,当延迟为 2ms 时,我就认为 Redis 变慢了,但是如果你的硬件配置比较高,那么在你的运行环境下,可能延迟是 0.5ms 时就可以认为 Redis 变慢了。

所以,你只有了解了你的 Redis 在生产环境服务器上的基准性能,才能进一步评估,当其延迟达到什么程度时,才认为 Redis 确实变慢了。

具体如何做?

为了避免业务服务器到 Redis 服务器之间的网络延迟,你需要直接在 Redis 服务器上测试实例的响应延迟情况。执行以下命令,就可以测试出这个实例 60 秒内的最大响应延迟:

$ redis-cli -h 127.0.0.1 -p 6379 --intrinsic-latency 60
Max latency so far: 1 microseconds.
Max latency so far: 15 microseconds.
Max latency so far: 17 microseconds.
Max latency so far: 18 microseconds.
Max latency so far: 31 microseconds.
Max latency so far: 32 microseconds.
Max latency so far: 59 microseconds.
Max latency so far: 72 microseconds.

1428669267 total runs (avg latency: 0.0420 microseconds / 42.00 nanoseconds per run).
Worst run took 1429x longer than the average latency.

从输出结果可以看到,这 60 秒内的最大响应延迟为 72 微秒(0.072毫秒)。

你还可以使用以下命令,查看一段时间内 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
...

以上输出结果是,每间隔 1 秒,采样 Redis 的平均操作耗时,其结果分布在 0.08 ~ 0.13 毫秒之间。

了解了基准性能测试方法,那么你就可以按照以下几步,来判断你的 Redis 是否真的变慢了:

  1. 在相同配置的服务器上,测试一个正常 Redis 实例的基准性能
  2. 找到你认为可能变慢的 Redis 实例,测试这个实例的基准性能
  3. 如果你观察到,这个实例的运行延迟是正常 Redis 基准性能的 2 倍以上,即可认为这个 Redis 实例确实变慢了

确认是 Redis 变慢了,那如何排查是哪里发生了问题呢?

下面跟着我的思路,我们从易到难,一步步来分析可能导致 Redis 变慢的因素。

使用复杂度过高的命令

首先,第一步,你需要去查看一下 Redis 的慢日志(slowlog)。

Redis 提供了慢日志命令的统计功能,它记录了有哪些命令在执行时耗时比较久。

查看 Redis 慢日志之前,你需要设置慢日志的阈值。例如,设置慢日志的阈值为 5 毫秒,并且保留最近 500 条慢日志记录:

# 命令执行耗时超过 5 毫秒,记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近 500 条慢日志
CONFIG SET slowlog-max-len 500

设置完成之后,所有执行的命令如果操作耗时超过了 5 毫秒,都会被 Redis 记录下来。

此时,你可以执行以下命令,就可以查询到最近记录的慢日志:

127.0.0.1:6379> SLOWLOG get 5
1) 1) (integer) 32693       # 慢日志ID
   2) (integer) 1593763337  # 执行时间戳
   3) (integer) 5299        # 执行耗时(微秒)
   4) 1) "LRANGE"           # 具体执行的命令和参数
      2) "user_list:2000"
      3) "0"
      4) "-1"
2) 1) (integer) 32692
   2) (integer) 1593763337
   3) (integer) 5044
   4) 1) "GET"
      2) "user_info:1000"
...

通过查看慢日志,我们就可以知道在什么时间点,执行了哪些命令比较耗时。

如果你的应用程序执行的 Redis 命令有以下特点,那么有可能会导致操作延迟变大:

  1. 经常使用 O(N) 以上复杂度的命令,例如 SORT、SUNION、ZUNIONSTORE 聚合类命令
  2. 使用 O(N) 复杂度的命令,但 N 的值非常大

第一种情况导致变慢的原因在于,Redis 在操作内存数据时,时间复杂度过高,要花费更多的 CPU 资源。

第二种情况导致变慢的原因在于,Redis 一次需要返回给客户端的数据过多,更多时间花费在数据协议的组装和网络传输过程中。

另外,我们还可以从资源使用率层面来分析,如果你的应用程序操作 Redis 的 OPS 不是很大,但 Redis 实例的 CPU 使用率却很高,那么很有可能是使用了复杂度过高的命令导致的。

除此之外,我们都知道,Redis 是单线程处理客户端请求的,如果你经常使用以上命令,那么当 Redis 处理客户端请求时,一旦前面某个命令发生耗时,就会导致后面的请求发生排队,对于客户端来说,响应延迟也

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值