0%

9、应对变慢的Redis

应对变慢的Redis

1、 获取 Redis 实例在当前环境下的基线性能。

从 2.8.7 版本开始,redis-cli 命令提供了–intrinsic-latency 选项

1
2
3
4
5
6
7
8
9
./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.

一般来说,你要把运行时延迟和基线性能进行对比,如果你观察到的 Redis 运行时延迟是其基线性能的 2 倍及以上,就可以认定 Redis 变慢了。

2、是否用了慢查询命令?

如果是的话,就使用其他命令替代慢查询命令,或者把聚合计算命令放在客户端做。

使用复杂度过高的命令(例如SORT/SUION/ZUNIONSTORE/KEYS),或一次查询全量数据(例如LRANGE key 0 N,但N很大)

分析:

  • a) 查看slowlog是否存在这些命令
  • b) Redis进程CPU使用率是否飙升(聚合运算命令导致)

解决:

  • a) 不使用复杂度过高的命令,或用其他方式代替实现(放在客户端做)
  • b) 数据尽量分批查询(LRANGE key 0 N,建议N<=100,查询全量数据建议使用HSCAN/SSCAN/ZSCAN)

3、是否对过期 key 设置了相同的过期时间?

对于批量删除的 key,可以在每个 key 的过期时间上加一个随机数,避免同时删除。

分析:

  • a) 业务使用EXPIREAT/PEXPIREAT命令
  • b) Redis info中的expired_keys指标短期突增

解决:

  • a) 优化业务,过期增加随机时间,把时间打散,减轻删除过期key的压力
  • b) 运维层面,监控expired_keys指标,有短期突增及时报警排查

4、是否存在 bigkey?

对于 bigkey 的删除操作,如果你的 Redis 是 4.0 及以上的版本,可以直接利用异步线程机制减少主线程阻塞;如果是 Redis 4.0 以前的版本,可以使用 SCAN 命令迭代删除;对于 bigkey 的集合查询和聚合操作,可以使用 SCAN 命令在客户端完成。

分析:

  • a) slowlog出现很多SET/DELETE变慢命令(bigkey分配内存和释放内存变慢)
  • b) 使用redis-cli -h $host -p $port –bigkeys扫描出很多bigkey

解决:

  • a) 优化业务,避免存储bigkey
  • b) Redis 4.0+可开启lazy-free机制

5、Redis AOF 配置级别是什么?

业务层面是否的确需要这一可靠性级别?如果我们需要高性能,同时也允许数据丢失,可以将配置项 no-appendfsync-on-rewrite 设置为 yes,避免 AOF 重写和 fsync 竞争磁盘 IO 资源,导致 Redis 延迟增加。当然, 如果既需要高性能又需要高可靠性,最好使用高速固态盘作为 AOF 日志的写入盘。

分析:AOF使用awalys机制导致磁盘IO负载变高

解决:

  • a) 使用everysec机制
  • b) 丢失数据不敏感的业务不开启AOF

6、Redis 实例的内存使用是否过大?

如果是的话,就增加机器内存,或者是使用 Redis 集群,分摊单机 Redis 的键值对数量和内存压力。同时,要避免出现 Redis 和其他内存需求大的应用共享机器的情况。

分析:

  • a) 实例内存达到maxmemory,且写入量大,淘汰key压力变大
  • b) Redis info中的evicted_keys指标短期突增

解决:

  • a) 业务层面,根据情况调整淘汰策略(随机比LRU快)
  • b) 运维层面,监控evicted_keys指标,有短期突增及时报警
  • c) 集群扩容,多个实例减轻淘汰key的压力

7、在 Redis 实例的运行环境中,是否启用了透明大页机制?

分析:

  • 生成RDB和AOF重写期间,主线程处理写请求耗时变长(拷贝内存副本耗时变长)

解决:

  • 直接关闭内存大页机制就行了。

8、是否运行了 Redis 主从集群?

如果是的话,把主库实例的数据量大小控制在 2~4GB,以免主从复制时,从库因加载大的 RDB 文件而阻塞。

9、是否使用了多核 CPU 或 NUMA 架构的机器运行 Redis 实例?

  • 使用多核 CPU 时,可以给 Redis 实例绑定物理核;
  • 使用 NUMA 架构时,注意把 Redis 实例和网络中断处理程序运行在同一个 CPU Socket 上。

10、进程绑定CPU不合理

分析:

  • a) Redis进程只绑定一个CPU逻辑核
  • b) NUMA架构下,网络中断处理程序和Redis进程没有绑定在同一个CPU Socket下

解决:

  • a) 一个 Redis 实例对应绑一个物理核
  • b) 网络中断处理程序和Redis进程绑定在同一个CPU Socket下

11、使用Swap?

分析:

  • a) 所有请求全部开始变慢
  • b) slowlog大量慢日志
  • c) 查看Redis进程是否使用到了Swap

解决:

  • a) 增加机器内存
  • b) 集群扩容
  • c) Swap使用时监控报警

12、网卡负载过高

分析:

  • a) TCP/IP层延迟变大,丢包重传变多

  • b) 是否存在流量过大的实例占满带宽

解决:

  • a) 机器网络资源监控,负载过高及时报警
  • b) 提前规划部署策略,访问量大的实例隔离部署