消息中间件——Redis—阻塞分析(五)

前言

Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现阻塞,哪怕是很短时间,对于应用来说都是噩梦。

导致阻塞问题的原因

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

发现阻塞

  • 应用方加入异常监控,如日志系统,比如Java语言中的logback或log4j
  • Redis监控系统,如CacheCloud

内在原因

API或数据结构使用不合理

对于高并发的场景应该尽量避免在大对象上执行算法复杂度超过O(n)的命令。

慢查询

Redis原生提供慢查询统计功能,执行slowlog get{n}命令可以获取最近的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令。

发现慢查询后如何调整:

  • 修改为低算法复杂度的命令

大对象

Redis本身提供发现大对象的工具。具体命令:
redis-cli -h {ip} -p {port} –bigkeys

内部原理采用分段进行scan操作,把历史扫描过的最大对象统计出来便于分析优化。

发现大对象如何调整:

  • 调整大对象:缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操作过多的数据。

CPU饱和

单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把单核CPU使用率跑到接近100%。CPU饱和是非常危险的,将导致Redis无法处理更多的命令,严重影响吞吐量和应用方的稳定性。

对于这种情况,首先判断当前Redis的并发量是否达到极限,建议使用统计命令redis-cli -h {ip} -p {port} –stat获取当前Redis使用情况

持久化阻塞

对于开启了持久化功能的Redis节点,需要排查是否是持久化导致的阻塞。

fork阻塞:fork操作发生在RDB和AOF重写时,Redis主线程调用fork操作产生共享内存的子进程,由子进程完成持久化文件重写工作。如果fork操作本身耗时过长,必然会导致主线程的阻塞。

AOF刷盘阻塞:当我们开启AOF持久化功能时,文件刷盘的方式一般采用每秒一次,后台线程每秒对AOF文件做fsync操作。当硬盘压力过大时,fsync操作需要等待,直到写入完成。如果主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操作完成。这种阻塞行为主要是硬盘压力引起。

HugePage写操作阻塞:子进程在执行重写期间利用Linux写时复制技术降低内存开销,因此只有写操作时Redis才复制要修改的内存页。对于开启Transparent HugePages的操作系统,每次写命令引起的复制内存页单位由4K变为2MB,放大了512倍,会拖慢写操作的执行时间,导致大量写操作慢查询。

外在原因

CPU竞争

进程竞争:Redis是典型的CPU密集型应用,不建议和其他多核CPU密集型服务部署在一起。当其他进程过度消耗CPU时,将严重影响Redis吞吐量。可以通过top、sar等命令定位到CPU消耗的时间点和具体进程,这个问题比较容易发现,需要调整服务之间部署结构。

绑定CPU:部署Redis时为了充分利用多核CPU,通常一台机器部署多个实例。常见的一种优化是把Redis进程绑定到CPU上,用于降低CPU频繁上下文切换的开销。这个优化技巧正常情况下没有问题,但是存在例外情况,当Redis父进程创建子进程进行RDB/AOF重写时,如果做了CPU绑定,会与父进程共享使用一个CPU。子进程重写时对单核CPU使用率通常在90%以上,父进程与子进程将产生激烈CPU竞争,极大影响Redis稳定性。因此对于开启了持久化或参与复制的主节点不建议绑定CPU。

内存交换

内存交换(swap)对于Redis来说是非常致命的,Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出到硬盘,由于内存与硬盘读写速度差几个数量级,会导致发生交换后的Redis性能急剧下降。

预防内存交换:

  • 保证机器充足的可用内存。
  • 确保所有Redis实例设置最大可用内存(maxmemory),防止极端情况下Redis内存不可控的增长。
  • 降低系统使用swap优先级。

网络问题

连接拒绝

  • 网络闪断(网络割接或者带宽耗尽)
  • Redis连接拒绝(超过客户端最大连接数)
  • 连接溢出(进程限制或backlog队列溢出)

网络延迟

网络延迟取决于客户端到Redis服务器之间的网络环境。主要包括它们之间的物理拓扑和带宽占用情况。常见的物理拓扑按网络延迟由快到慢可分为:同物理机>同机架>跨机架>同机房>同城机房>异地机房。但它们容灾性正好相反,同物理机容灾性最低而异地机房容灾性最高。

网络延迟问题经常出现在跨机房的部署结构上,对于机房之间延迟比较严重的场景需要调整拓扑结构,如把客户端和Redis部署在同机房或同城机房等。

带宽瓶颈通常出现在以下几个方面:

  • 机器网卡带宽。
  • 机架交换机带宽。
  • 机房之间专线带宽。

网卡软中断

网卡软中断是指由于单个网卡队列只能使用一个CPU,高并发下网卡数据交互都集中在同一个CPU,导致无法充分利用多核CPU的情况。网卡软中断瓶颈一般出现在网络高流量吞吐的场景。

文章目录
  1. 1. 前言
  2. 2. 导致阻塞问题的原因
  3. 3. 发现阻塞
  4. 4. 内在原因
    1. 4.1. API或数据结构使用不合理
      1. 4.1.1. 慢查询
      2. 4.1.2. 大对象
    2. 4.2. CPU饱和
    3. 4.3. 持久化阻塞
  5. 5. 外在原因
    1. 5.1. CPU竞争
    2. 5.2. 内存交换
    3. 5.3. 网络问题
      1. 5.3.1. 连接拒绝
      2. 5.3.2. 网络延迟
      3. 5.3.3. 网卡软中断
|