Redis AOF重写阻塞因素

持久化阻塞


对于开启了持久化功能的Redis节点, 需要排查是否是持久化导致的阻塞。 持久化引起主线程阻塞的操作主要有: fork阻塞、 AOF刷盘阻塞、HugePage写操作阻塞。

 

fork操作


当Redis做RDB或AOF重写时, 一个必不可少的操作就是执行fork操作创建子进程, 对于大多数操作系统来说fork是个重量级错误 虽然fork创建的子进程不需要拷贝父进程的物理内存空间, 但是会复制父进程的空间内存页表。 例如对于10GB的Redis进程, 需要复制大约20MB的内存页表, 因此fork操作耗时跟进程总内存量息息相关, 如果使用虚拟化技术, 特别是Xen虚拟机, fork操作会更耗时。

fork耗时问题定位: 对于高流量的Redis实例OPS可达5万以上 如果fork操作耗时在秒级别将拖慢Redis几万条命令执行, 对线上应用延迟影响非常明显。 正常情况下fork耗时应该是每GB消耗20毫秒左右。 可以在info stats统计中查latest_fork_usec指标获取最近一次fork操作耗时, 单位微秒。

如何改善fork操作的耗时:
1) 优先使用物理机或者高效支持fork操作的虚拟化技术, 避免使用Xen。
2) 控制Redis实例最大可用内存, fork耗时跟内存量成正比, 线上建议每个Redis实例内存控制在10GB以内。
3) 合理配置Linux内存分配策略, 避免物理内存不足导致fork失败
4) 降低fork操作的频率, 如适度放宽RDB自动触发时机, 避免不必要的全量复制等

 
  1.  

    [root@localhost ~]# /usr/local/redis//bin/redis-cli bgsave
    
    Background saving started
    
    
    
    
    [root@localhost ~]# tail -f /usr/local/redis/redis_6379.log
    
    1320:M 06 May 2020 21:57:12.690 * Background saving started by pid 20322
    
    20322:C 06 May 2020 21:57:12.771 * DB saved on disk
    
    20322:C 06 May 2020 21:57:12.772 * RDB: 4 MB of memory used by copy-on-write
    
    1320:M 06 May 2020 21:57:12.781 * Background saving terminated with success
    
    
    
    [root@localhost ~]# /usr/local/redis/bin//redis-cli info stats | grep la
    
    
    latest_fork_usec:37470

     

 

fork阻塞


fork操作发生在RDB和AOF重写时, Redis主线程调用fork操作产生共享内存的子进程, 由子进程完成持久化文件重写工作。 如果fork操作本身耗时过长, 必然会导致主线程的阻塞。可以执行info stats命令获取到latest_fork_usec指标, 表示Redis最近一次
fork操作耗时, 如果耗时很大, 比如超过1秒, 则需要做出优化调整, 如避免使用过大的内存实例和规避fork缓慢的操作系统等。
 

 

AOF刷盘阻塞


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

 
  1.  

    Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF
    
    buffer without waiting for fsync to complete, this may slow down Redis.

     

也可以查看info persistence统计中的aof_delayed_fsync指标, 每次发生datasync阻塞主线程时会累加。 
 

当开启AOF持久化时, 常用的同步硬盘的策略是everysec, 用于平衡性能和数据安全性。 对于这种方式, Redis使用另一条线程每秒执行fsync同步硬盘。 当系统硬盘资源繁忙时, 会造成Redis主线程阻塞, 如图5-5所示。
                                             

阻塞流程分析:
1) 主线程负责写入AOF缓冲区。
2) AOF线程负责每秒执行一次同步磁盘操作,并记录最近一次同步时间(AOF线程复制统计时间,主线程负责对比和上次时间差)
3) 主线程负责对比上次AOF同步时间:
·如果距上次同步成功时间在2秒内, 主线程直接返回。
·如果距上次同步成功时间超过2秒, 主线程将会阻塞, 直到同步操作完成

通过对AOF阻塞流程可以发现两个问题:
1) everysec配置最多可能丢失2秒数据, 不是1秒。
2) 如果系统fsync缓慢, 将会导致Redis主线程阻塞影响效率。

AOF阻塞问题定位:
1) 发生AOF阻塞时, Redis输出如下日志, 用于记录AOF fsync阻塞导致拖慢Redis服务的行为:

 
  1.  

    Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF buffer
    
    without waiting for fsync to complete, this may slow down Redis

     

2) 每当发生AOF追加阻塞事件发生时, 在info Persistence统计中,aof_delayed_fsync指标会累加, 查看这个指标方便定位AOF阻塞问题。

 
  1.  

    [root@localhost ~]# /usr/local/redis/bin/redis-cli info | grep aof_delay
    
    aof_delayed_fsync:0

     

3) AOF同步最多允许2秒的延迟, 当延迟发生时说明硬盘存在高负载问题, 可以通过监控工具如iotop, 定位消耗硬盘IO资源的进程。

运维提示
硬盘压力可能是Redis进程引起的, 也可能是其他进程引起的, 可以使用iotop查看具体是哪个进程消耗过多的硬盘资源。

 

HugePage写操作阻塞


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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值