Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现阻塞,哪怕是短时间,对于我们应用来说都是噩梦。导致阻塞问题的场景大致分为内在原因和外在原因:
- 内在原因包括:不合理地使用API或数据结构、CPU饱和、持久化阻塞等。
- 外在原因包括:CPU竞争、内存交换、网络问题等。
一、内在原因:
1.API 或 数据结构 使用不合理
排查:
- 发现慢查询:执行
slowlog get {n}
- 发现大对象:执行
redis-cli -h {ip} -p {port} --bigkeys
解决:
- 解决慢查询:调整命令为低算法度命令
- 调整大对象:把大对象拆分为多个小对象,防止一次命令操作过多数据
CPU饱和
排查
- 查看CPU使用率:执行
top
命令 - 查询Redis并发量:执行
redis-cli -h {ip} -p {port} --stat
命令
解决:
- 集群化水平拓展分摊OPS压力
- 检查是否有过度的内存优化
持久化阻塞
排查
- 检查最近fork操作耗时:执行
info status
获取到 latest_fork_usec 指标 - 检查AOF刷盘最近成功时间:查看日志
解决:
- 若fork操作耗时超过1秒,避免使用过大的内存实例和规避fork缓慢的操作系统
- 若AOF刷盘fsync成功操作超过2秒,降低其他进程对硬盘的压力
二、外在原因
1.CPU竞争
排查:执行 top
或 sar
命令
解决:
- 不建议和其他多核CPU密集型服务部署在一起,会影响Redis吞吐量
- 把Redis进程绑定到CPU上,可降低CPU上下文切换开销
- 开启了持久化或参与复制的主节点不建议绑定CPU,因为子进程会占用90%竞争
2.内存交换
排查:
- 查询Redis进程号:执行
redis-cli -p 6383 info server | grep process_id
命令 - 根据进程号查询内存交换信息:执行
cat /proc/process_id/smaps | grep Swap
解决:
- 保证机器充足的可用内存
- 确保所有Redis实例设置最大可用内存,防止Redis不可控增长
- 降低系统使用swap优先级
3.网络问题
排查:
-
网络闪断:通过
sar -n DEV
查看本机历史流量是否正常 -
Redis连接拒绝:执行
redis-cli -p 6384 info stats | grep rejected_connections
查看所有被拒绝的连接数量 -
连接溢出:指操作系统或者Redis客户端在连接时的问题。原因比较多,可能有进程限制、backlog队列溢出。执行
ulimit -n
命令,检查操作系统对进程使用资源的限制;执行netstat -s | grep overflowed
命令,检查是否有持续增长的连接拒绝 -
网络延迟:执行
redis-cli -h {host} -p {port} --latency
命令,测量机器之间的网络延迟
解决:
- 避免客户端与Redis之间异地跨机房调用
- 客户端访问Redis时尽量采用NIO长连接或者连接池的方式
- 对于支撑大量连接的Redis需要增大 ulimit 值,修改系统backlog值
- 调整网络拓扑结构,同物理机>同机架>跨机架>同机房>同城机房>异地机房
资料
合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!