从文件系统和操作系统两个维度,介绍了应对Redis变慢的方法。
为了方便你应用,我给你梳理了一个包含9个检查点的Checklist,希望你在遇到Redis性能变慢时,按照这些步骤逐一检查,高效地解决问题。
获取Redis实例在当前环境下的基线性能。
是否用了慢查询命令?
如果是的话,就使用其他命令替代慢查询命令,或者把聚合计算命令放在客户端做。
是否对过期key设置了相同的过期时间?对于批量删除的key,可以在每个key的过期时间上加一个随机数,避免同时删除。
3.是否存在bigkey?
对于bigkey的删除操作,如果你的Redis是4.0及以上的版本,可以直接利用异步线程机制减少主线程阻塞;如果是Redis 4.0以前的版本,可以使用SCAN命令迭代删除;对于bigkey的集合查询和聚合操作,可以使用SCAN命令在客户端完成。
4.Redis AOF配置级别是什么?业务层面是否的确需要这一可靠性级别?
如果我们需要高性能,同时也允许数据丢失,可以将配置项no-appendfsync-on-rewrite设置为yes,避免AOF重写和fsync竞争磁盘IO资源,导致Redis延迟增加。当然, 如果既需要高性能又需要高可靠性,最好使用高速固态盘作为AOF日志的写入盘。
5.Redis实例的内存使用是否过大?发生swap了吗?
如果是的话,就增加机器内存,或者是使用Redis集群,分摊单机Redis的键值对数量和内存压力。同时,要避免出现Redis和其他内存需求大的应用共享机器的情况。
- 在Redis实例的运行环境中,是否启用了透明大页机制?
如果是的话,直接关闭内存大页机制就行了。
- 是否运行了Redis主从集群?
如果是的话,把主库实例的数据量大小控制在2~4GB,以免主从复制时,从库因加载大的RDB文件而阻塞。
8.是否使用了多核CPU或NUMA架构的机器运行Redis实例?
使用多核CPU时,可以给Redis实例绑定物理核;使用NUMA架构时,注意把Redis实例和网络中断处理程序运行在同一个CPU Socket上。
实际上,影响系统性能的因素还有很多,这些都是应对最常见问题的解决方案。
如果你遇到了一些特殊情况,也不要慌,我再给你分享一个小技巧:
仔细检查下有没有恼人的“邻居”,具体点说,就是Redis所在的机器上有没有一些其他占内存、磁盘IO和网络IO的程序,比如说数据库程序或者数据采集程序。
如果有的话,我建议你将这些程序迁移到其他机器上运行。
为了保证Redis高性能,我们需要给Redis充足的计算、内存和IO资源,给它提供一个“安静”的环境。
关于如何分析、排查、解决Redis变慢问题,我总结的checklist如下:
1、使用复杂度过高的命令(例如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)
2、操作bigkey
分析:
a) slowlog出现很多SET/DELETE变慢命令(bigkey分配内存和释放内存变慢)
b) 使用redis-cli -h port --bigkeys扫描出很多bigkey
解决:
a) 优化业务,避免存储bigkey
b) Redis 4.0+可开启lazy-free机制
3、大量key集中过期
分析:
a) 业务使用EXPIREAT/PEXPIREAT命令
b) Redis info中的expired_keys指标短期突增
解决:
a) 优化业务,过期增加随机时间,把时间打散,减轻删除过期key的压力
b) 运维层面,监控expired_keys指标,有短期突增及时报警排查
4、Redis内存达到maxmemory
分析:
a) 实例内存达到maxmemory,且写入量大,淘汰key压力变大
b) Redis info中的evicted_keys指标短期突增
解决:
a) 业务层面,根据情况调整淘汰策略(随机比LRU快)
b) 运维层面,监控evicted_keys指标,有短期突增及时报警
c) 集群扩容,多个实例减轻淘汰key的压力
5、大量短连接请求
分析:Redis处理大量短连接请求,TCP三次握手和四次挥手也会增加耗时
解决:使用长连接操作Redis
6、生成RDB和AOF重写fork耗时严重
分析:
a) Redis变慢只发生在生成RDB和AOF重写期间
b) 实例占用内存越大,fork拷贝内存页表越久
c) Redis info中latest_fork_usec耗时变长
解决:
a) 实例尽量小
b) Redis尽量部署在物理机上
c) 优化备份策略(例如低峰期备份)
d) 合理配置repl-backlog和slave client-output-buffer-limit,避免主从全量同步
e) 视情况考虑关闭AOF
f) 监控latest_fork_usec耗时是否变长
7、AOF使用awalys机制
分析:磁盘IO负载变高
解决:
a) 使用everysec机制
b) 丢失数据不敏感的业务不开启AOF
8、使用Swap
分析:
a) 所有请求全部开始变慢
b) slowlog大量慢日志
c) 查看Redis进程是否使用到了Swap
解决:
a) 增加机器内存
b) 集群扩容
c) Swap使用时监控报警
9、进程绑定CPU不合理
分析:
a) Redis进程只绑定一个CPU逻辑核
b) NUMA架构下,网络中断处理程序和Redis进程没有绑定在同一个Socket下
解决:
a) Redis进程绑定多个CPU逻辑核
b) 网络中断处理程序和Redis进程绑定在同一个Socket下
10、开启透明大页机制
分析:生成RDB和AOF重写期间,主线程处理写请求耗时变长(拷贝内存副本耗时变长)
解决:关闭透明大页机制
11、网卡负载过高
分析:
a) TCP/IP层延迟变大,丢包重传变多
b) 是否存在流量过大的实例占满带宽
解决:
a) 机器网络资源监控,负载过高及时报警
b) 提前规划部署策略,访问量大的实例隔离部署
总之,Redis的性能与CPU、内存、网络、磁盘都息息相关,任何一处发生问题,都会影响到Redis的性能。
主要涉及到的包括业务使用层面和运维层面:
业务人员需要了解Redis基本的运行原理,使用合理的命令、规避bigke问题和集中过期问题。
运维层面需要DBA提前规划好部署策略,预留足够的资源,同时做好监控,这样当发生问题时,能够及时发现并尽快处理。
参考
Redis响应严重延迟,如何解决?
https://ibyte.blog.csdn.net/article/details/108846620
Redis在持久化时产生的延迟
https://hiddenpps.blog.csdn.net/article/details/94518679
游戏陪玩源码中,Redis 发生高延迟的原因是什么?
https://blog.csdn.net/m0_58374018/article/details/122218778·