• 18.Redis系列之AOF方式持久化


    本文学习redis7两大持久化技术之一:AOF(Append Only File)日志追加方式持久化备份与还原,重写以及AOF方式的优缺点

    1. AOF相关配置

    首先我们先简单了解下Redis7中AOF相关配置

    // 开启AOF方式持久化,默认no
    appendonly yes
    // AOF持久化名称
    appendfilename "appendonly.aof"
    // AOF持久化文件存储目录
    appenddirname "appendonlydir"
    // fsync数据到磁盘策略:默认每秒everysec
    appendfsync everysec
    // AOF重写时不进行fsync操作,防止redis长时间阻塞
    no-appendfsync-on-rewrite no
    // AOF重写最小大小为64M,当AOF文件大小扩展一倍时触发重写:如128M, 192M
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    // 当AOF结尾异常,Redis加载时截取正确部分,恢复时不报错,仅仅日志提示
    aof-load-truncated yes
    // append-only基础文件采用RDB格式 
    aof-use-rdb-preamble yes
    // AOF记录命令执行时间戳,默认no
    aof-timestamp-enabled no
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    2. AOF备份还原实践
    2.1 AOF文件正常情况下还原

    修改配置文件为appendonly yes,并启动redis

    1

    可以看到redis7中,在appendonlydir目录下生成了

    • rdb基础文件
    • incr增量文件
    • manifest管理文件

    继续执行以前的测试文件

    @SpringBootTest
    public class RedisTest {
    
        @Autowired
        private RedissonClient redissonClient;
    
        @Test
        public void testRdb() throws InterruptedException {
            RMap<String, String> rMap = redissonClient.getMap("rdb");
            for (int i = 0; i < 10020; i++) {
                rMap.put(i + "", i + "");
            }
            Thread.sleep(60000);
            for (int i = 0; i < 80; i++) {
                rMap.put(i + "ok", i + "ok");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    操作后我们尝试修改appendonlydir目录名,发现只读不允许修改,我们复制一份重命名为appendonlydirbak模拟备份文件,然后执行

    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> shutdown
    
    • 1
    • 2
    • 3

    然后我们删除appendonlydir目录,重命名appendonlydirbak为appendonlydir,然后启动redis, 执行hkeys rdb如图所示,key数量为10100未丢失

    2

    我们同时配置了RDB与AOF,但redis会已AOF为准进行恢复

    2.2 AOF异常状况下进行还原

    我们关闭redis服务器,执行命令破坏incr.aof文件

    /data # echo 'HELLO WORLD' >> /data/appendonlydir/appendonly.aof.1.incr.aof
    
    • 1

    当我们重启redis发现无法正常启动,我们使用redis-check-aof工具检查错误

    /data # redis-check-aof  /data/appendonlydir/appendonly.aof.1.incr.aof
    Start checking Old-Style AOF
    AOF /data/appendonlydir/appendonly.aof.1.incr.aof format error
    AOF analyzed: filename=/data/appendonlydir/appendonly.aof.1.incr.aof, size=492735, ok_up_to=492723, ok_up_to_line=90906, diff=12
    AOF /data/appendonlydir/appendonly.aof.1.incr.aof is not valid. Use the --fix option to try fixing it.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    /data # redis-check-aof --fix /data/appendonlydir/appendonly.aof.1.incr.aof
    Start checking Old-Style AOF
    AOF /data/appendonlydir/appendonly.aof.1.incr.aof format error
    AOF analyzed: filename=/data/appendonlydir/appendonly.aof.1.incr.aof, size=492735, ok_up_to=492723, ok_up_to_line=90906, diff=12
    This will shrink the AOF /data/appendonlydir/appendonly.aof.1.incr.aof from 492735 bytes, with 12 bytes, to 492723 bytes
    y // 输入y才弹出来Continue,然后继续输入y
    Continue? [y/N]: Successfully truncated AOF /data/appendonlydir/appendonly.aof.1.incr.aof
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    修复aof文件后,可以观察到appendonly.aof.1.incr.aof中HELLO WORLD被移除,并可以正常重新启动redis

    3. AOF持久化原理
    3.1 AOF持久化三大步骤

    我们采用伪代码来表示持久化实现的三大步骤:命令追加至aof_buf缓冲区、aof_buf缓冲写入aof文件、fsync文件同步[说白点类似将word中写入的值点击保存至磁盘]

    def evenLoop():
        while True:
            // 处理文件事件,接受命令请求以及发送命令回复
            // 处理写请求追加到aof_buf缓冲区
            processFileEvents()
     
            // 处理时间事件
            processTimeEvents()
            
            // 根据持久化策略,也就是appendfsync的配置选择是否将aof_buf缓冲写入并保存到aof文件
            flushAppendOnlyFile()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    redis进程就是一个事件循环(loop),循环中的文件事件负责处理客户端请求并响应,当AOF配置appendonly打开时,文件事件处理完写命令后,会将写命令已redis协议格式追加到aof_buf缓冲区末尾【如上图所示】;对于时间事件,则运行定时函数;

    3.2 文件写入与同步策略

    对于flushAppendOnlyFile()函数,也就是文件写入与同步步骤是由appendfsync配置决定

    • appendfsync everysec: 每个事件循环都要将aof_buf缓冲值写入aof文件,每秒fsync同步至磁盘
    • appendfsync always: 每个事件循环都要将aof_buf缓冲值写入aof文件,并立即fsync同步至磁盘,效率最低,三者中也最安全
    • appendfsync no: 每个事件循环都要将aof_buf缓冲值写入aof文件,由操作系统决定何时 fsync同步至磁盘,一般30s,效率最高,三者中最不安全
    4. AOF重写实践与流程

    当redis写命令越来越多,aof会越来越大,达到重写配置条件,或者手工执行bgrewriteaof时会触发重写机制已减少aof大小

    // AOF重写时不进行fsync操作,防止redis长时间阻塞
    no-appendfsync-on-rewrite no
    // AOF重写最小大小为64M,当AOF文件大小扩展一倍时触发重写:如128M, 192M
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.1 AOF重写实践

    我们先记录下.incr.aof文件当前的行数为90805,再次执行上述java批量写入命令,我们发现目前行数增加至181810行,体积变为900K,现在我们执行BGREWRITEAOF重写后,我们发现incr.aof为空了,且base.rdb文件大小由1K增加156K

    127.0.0.1:6379> BGREWRITEAOF
    Background append only file rewriting started
    
    • 1
    • 2

    3
    4

    4.2 AOF重写流程

    当redis版本>=7时,流程如下:

    • redis fork出子进程,此时存在父进程与子进程
    • 子进程开始重写一个新的base aof文件【我们刚重写的是2.base.rdb】到临时文件
    • 父进程打开一个新的incr.aof增量文件【2.incr.aof文件】处理客户端写请求,即使重写失败,manifest文件指向1.base.rdb+2.incr.aof增量文件,所以安全性有保障
    • 当子进程重写完base aof文件,父进程会接收到信号,会使用新的base aof文件和新的incr.aof增量文件来构建一个临时manifest文件,并将manifest、2.base.rdb临时文件持久化
    • redis现在原子性替换manifest文件已使得AOF重写生效,并清理旧的1.base.rdb文件和无用增量文件[1.incr.aof]

    当然在低于7版本是通过AOF重写缓冲区实现的,在此不在讨论

    5. AOF优缺点

    优点:

    • 相对于rdb而言,提供了三种fsync同步策略,数据备份更加安全
    • AOF仅仅追加写命令,不会因为断电寻道导致文件损坏,即使损坏也很容易恢复
    • 当AOF文件过大时,redis能够在后台自动重写
    • AOF协议文本格式易于理解操作,即使flushall删库,只要没有发生重写,仍然可以停止服务器,删除incr.aof中flushall命令,重启数据库来还原

    缺点:

    • AOF文件通常比RDB快照文件大
    • AOF数据还原可能比RDB慢,取决于具体fsync策略,禁用fsync策略高负载下也同样和rdb一样快,everysec性能仍然非常高
    • 低于redis7版本时,AOF重写可能会使用大量内存

    欢迎关注公众号 算法小生 获取更多精彩内容

  • 相关阅读:
    [附源码]java毕业设计文具销售系统
    【循环冗余码检错示例】
    计组——cache替换算法及cache写策略
    记某同事的两次误操作导致Linux瘫痪
    MSQL系列(九) Mysql实战-Join算法底层原理
    CMSC5707-高级人工智能之音频信号特征提取
    springcloud使用openFeign
    架构思考(八)
    camunda7流程跳转和流程退回的实现方法
    python实现Flask POST Demo
  • 原文地址:https://blog.csdn.net/SJshenjian/article/details/127935437