Redis的噩梦:阻塞

Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现阻塞,哪怕是短时间,对于我们应用来说都是噩梦。导致阻塞问题的场景大致分为内在原因和外在原因:

  • 内在原因包括:不合理地使用API或数据结构、CPU饱和、持久化阻塞等。
  • 外在原因包括:CPU竞争、内存交换、网络问题等。

image.png

一、内在原因:

1.API 或 数据结构 使用不合理

排查:

  1. 发现慢查询:执行 slowlog get {n}
  2. 发现大对象:执行 redis-cli -h {ip} -p {port} --bigkeys

解决:

  1. 解决慢查询:调整命令为低算法度命令
  2. 调整大对象:把大对象拆分为多个小对象,防止一次命令操作过多数据

CPU饱和

排查

  1. 查看CPU使用率:执行 top 命令
  2. 查询Redis并发量:执行 redis-cli -h {ip} -p {port} --stat 命令

解决:

  1. 集群化水平拓展分摊OPS压力
  2. 检查是否有过度的内存优化

持久化阻塞

排查

  1. 检查最近fork操作耗时:执行 info status 获取到 latest_fork_usec 指标
  2. 检查AOF刷盘最近成功时间:查看日志

解决:

  1. 若fork操作耗时超过1秒,避免使用过大的内存实例和规避fork缓慢的操作系统
  2. 若AOF刷盘fsync成功操作超过2秒,降低其他进程对硬盘的压力

二、外在原因

1.CPU竞争

排查:执行 top 或 sar 命令

解决:

  • 不建议和其他多核CPU密集型服务部署在一起,会影响Redis吞吐量
  • 把Redis进程绑定到CPU上,可降低CPU上下文切换开销
  • 开启了持久化或参与复制的主节点不建议绑定CPU,因为子进程会占用90%竞争

2.内存交换

排查:

  1. 查询Redis进程号:执行 redis-cli -p 6383 info server | grep process_id 命令
  2. 根据进程号查询内存交换信息:执行 cat /proc/process_id/smaps | grep Swap

解决:

  1. 保证机器充足的可用内存
  2. 确保所有Redis实例设置最大可用内存,防止Redis不可控增长
  3. 降低系统使用swap优先级

3.网络问题

排查:

  1. 网络闪断:通过 sar -n DEV 查看本机历史流量是否正常

  2. Redis连接拒绝:执行 redis-cli -p 6384 info stats | grep rejected_connections查看所有被拒绝的连接数量

  3. 连接溢出:指操作系统或者Redis客户端在连接时的问题。原因比较多,可能有进程限制、backlog队列溢出。执行ulimit -n命令,检查操作系统对进程使用资源的限制;执行 netstat -s | grep overflowed命令,检查是否有持续增长的连接拒绝

  4. 网络延迟:执行redis-cli -h {host} -p {port} --latency 命令,测量机器之间的网络延迟

解决:

  1. 避免客户端与Redis之间异地跨机房调用
  2. 客户端访问Redis时尽量采用NIO长连接或者连接池的方式
  3. 对于支撑大量连接的Redis需要增大 ulimit 值,修改系统backlog值
  4. 调整网络拓扑结构,同物理机>同机架>跨机架>同机房>同城机房>异地机房

资料

redis阻塞原因以及处理方案

Redis阻塞整理笔记

合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

需要学习的内容

image.png

猜你喜欢

转载自juejin.im/post/7001674116105256974