zoukankan      html  css  js  c++  java
  • Redis关键点(自动bgrewriteaof)

    Redis 2.4版本做了很多功能改进,尤其是aof这块变动较大。增加了自动的bgrewriteaof,开启两个后台线程来避免主线程fsync、rename、close等阻塞操作,另外修复了出现重复命令进入aof文件的bug,下面是基于2.4.1的源码aof这块的改进分析。

    旧的版本问题主要有:

    • 1 主线程aof的每次fsync(everysecond模式)在高并发下时常出现100ms的延时,这源于fsync必不可少的磁盘操作,即便已经优化多次请求的离散小io转化成一次大的连续io(sina的同学也反映过这个问题).
    • 2 主线程里backgroundRewriteDoneHandler函数在处理bgrewriteaof后台进程退出的时候存在一个rename new-aof-file old-aof-file,然后再close old-aof-file的操作, close是一个unlink的操作(最后的引用计数), unlink消耗的时间取决于文件的大小,是个容易阻塞的系统调用.
    • 3 当发生bgsave或者bgrewriteaof的时候主线程和子进程同时写入不同的文件,这改变了原有连续写模式,不同写入点造成了磁盘磁头的寻道时间加长(其实一个台物理机多实例也有这个问题, 要避免同一时间点做bgrewriteaof), 这又加长了fsync时间.

    在2.4版里把fsync和close操作都移动到background来执行.

    解决问题1

    主线程仅仅把aofbuf的数据刷新到aof文件里,然后通过bioCreateBackgroundJob函数往这队列里插入fsync job,于是原有主线程的fsync工作被转移到后台线程来做,这样主线程阻塞问题就异步的解决了.

    但这又引发了一个问题,主线程对同一个fd如果有write操作,后台线程同时在fsync,这两个线程会互相影响. antirez为此做了一定研究,并给出了简单的解决方案.

    为了避免线程的互相影响,主线程每次write之前都要检测一下后台线程任务队列里是否有fsync操作,如果有则延迟这次aofbuf的flush,延迟flush这个功能,当然会增大丢数据的可能.

    解决缺陷2

    backgroundRewriteDoneHandler里同样的把close old-aof-file的工作交给backgroud thread来执行.

    解决缺陷3

    引入了延迟bgrewriteaof来避免与bgsave同时写文件,而server.no_appendfsync_on_rewrite参数的设置又避免了bgrewriteaof时主线程出现fsync.

     自动的bgrewriteaof

    为了避免aof文件过大,我们会周期性的做bgrewriteaof来重整aof文件。以前我们会额外的配置crontab在业务低峰期执行这个命令,这额外的增加一个workaroud的脚本任务在大集群里是很糟糕的,不易检查,出错无法即时发现。

    于是这个自动bgrewriteaof功能被直接加到redis的内部。首先对于aof文件,server对象添加一个字段来记录aof文件的大小server.appendonly_current_size,每次aof发生变化都会维护这个字段。

    bgrewriteaof完毕或者实例启动载入aof数据后也会调用aofUpdateCurrentSize这个函数维护这个字段,同时会记录下此时的aof文件的大小server.auto_aofrewrite_base_size作为基准值,用于接下来判断aof增长率。

    有了当前值和基准值我们就可以判断aof文件的增长情况。另外还需要配置两个参数来判断是否需要自动触发bgrewriteaof。

    auto_aofrewrite_perc: aof文件的大小超过基准百分之多少后触发bgrewriteaof。默认这个值设置为100,意味着当前aof是基准大小的两倍的时候触发bgrewriteaof。把它设置为0可以禁用自动触发的功能。
    auto_aofrewrite_min_size: 当前aof文件大于多少字节后才触发。避免在aof较小的时候无谓行为。默认大小为64mb。
    两个参数都是可以在conf里静态配置,或者通过config set来动态修改的。

    redis 127.0.0.1:6379> config get auto-aof-rewrite-percentage  
    1) "auto-aof-rewrite-percentage"  
    2) "100"  
    redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size  
    1) "auto-aof-rewrite-min-size"  
    2) "1048576"  
    redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size  
    1) "auto-aof-rewrite-min-size"  
    2) "1048576"  
    redis 127.0.0.1:6379> config set auto-aof-rewrite-percentage 200  
    OK  
    redis 127.0.0.1:6379> config set auto-aof-rewrite-min-size 10485760  
    OK  
    

      

    然后就是触发检查的主逻辑,serverCron时间事件中每次都会检查现有状态和参数来判断是否需要启动bgrewriteaof。

    如果aof文件增长百分率growth大于auto_aofrewrite_perc,则自动的触发后一个bgrewriteaof。

    延迟bgrewriteaof

    这是个小的改进,手动触发的bgrewriteaof的时候如果同时存在bgsave在备份,会推迟这次操走的事件,设置server.aofrewrite_scheduled=1,待到bgsave结束后的下一次serverCron里才会触发。

  • 相关阅读:
    C语言 · 阶乘计算 · 基础练习
    C语言 · 查找整数 · 基础练习
    UML课程复习重点
    运维参考
    mysql语法总结
    Python杂篇
    Python练习题
    Python参考
    k8s中ipvs和iptables选择
    安装cni网络插件-非必须
  • 原文地址:https://www.cnblogs.com/xzlive/p/14977006.html
Copyright © 2011-2022 走看看