为什么阻塞
- 内部原因
(1)redis采用单线程处理请求,reactor是同步IO,需要等待命令执行完成,才会返回执行结果,然后进入下一个请求(队列)
(2)持久化阻塞
(3)CPU饱和 - 外部原因
(1)不合理使用API和数据结构(bigkes、慢查询)
(2)网络问题(最大连接数、网络延迟)
(3)内存交换
持久化阻塞
- fork阻塞: fork操作发生在rdb和aof重写时,redis主线程调用fork操作产生共享内存的子进程,由子进程完成持久化文件重写工作,若fork操作本身耗时过长,则必会导致主线程阻塞;可执行info stats命令获取到latest_fork_usec指标,表示redis最近一次fork操作耗时,若超过1s,则需要做出优化调整
- aof刷盘阻塞: 当开启aof持久化功能时,文件刷盘的方式一般采用每秒一次,后台线程每秒对aof文件做fsync操作,硬盘压力过大时,fsync操作需要等待,直到写入完成如果主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操作完成,这种阻塞行为主要是硬盘压力引起,可查看Redis日志识别出这种情况
CPU饱和
单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把单核CPU使用率跑到接近100%。使用top命令很容易识别出对应Redis进程的CPU使用率。CPU饱和是非常危险的,将导致Redis无法处理更多的命令,严重影响吞吐量和应用方的稳定性。
应对之策是做好CPU监控报警策略,如果使用的阿里云redis,可以在阿里云后台设置CPU使用阈值预警
不合理使用API和数据结构(bigkes、慢查询)
-
使用大对象
- 将大对象拆分为小对象
- 发现大对象的命令:redis-cli -h{ip} -p{port} bigkeys ,内部原理采用分段进行scan操作,把历史扫描过的最大对象统计出来便于分析优化。
-
使用keys取出所有key
- keys [pattern] 一次性全部返回符合条件的key,如果数据量很大将会阻塞其他客户端
- 在数量未知或者数量较大的情况下使用scan遍历来获取所有的key
-
大量的key同时过期
- 如果有很多key在同一秒内过期,超过了所有key的25%,redis主线程就会阻塞直到过期key比例下降到25%以内
- 因为要避免大量的key同时过期
网络问题
- redis连接拒绝(超过客户端最大连接数)
- 网络延迟
- 网卡软中断(一般出现在网络高流量吞吐的场景)
内存交换
- 内存交换(swap)对于Redis来说是非常致命的,Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出到硬盘,由于内存与硬盘读写速度差几个数量级,会导致发生交换后的Redis性能急剧下降。
感谢
原文链接:https://www.jianshu.com/p/94a83f57bf94
原文链接:https://blog.csdn.net/linbiaorui/article/details/79822318
原文链接:https://www.jianshu.com/p/b8880db58241