• Redis 设计与实现 (三)--持久化


    RDB 持久化

     一、生成RDB

      cmd:SAVE  --阻塞进程,执行完,才能有效接收客户端命令。

      cmd:  BGSAVE  --非阻塞,开启子进程保存。

              客户端如果发送SAVE和BGSAVE命令直接拒绝。

              BGWRITEAOF命令再BGSAVE执行完才能执行。  

     二、载入RDB

      服务器启动时自动执行,检测到RDB文件就会自动加载。

      如果开启AOF,优先使用执行AOF。

      AOF关闭的情况下,才会执行RDB。

       

    三、自动间隔性保存

      save设置:一定条件后执行BGSAVE命令进行保存

      默认设置:

        save 900 1  //900秒内,进行一次修改,触发保存BGSAVE

        save 300 1  //300秒内,10次修改,触发保存BGSAVE  

        save 60  10000   //60秒内,1w次修改,触发保存BGSAVE 

    struct saveparam {
        time_t seconds; //秒数
        int changes;//变化次数
    };

    还有两个参数:

    dirty --上次数据库触发保存命令修改数   

    lastsave -- 最后一次执行save时间

    PORT_LONGLONG dirty;                /* Changes to DB from the last save */ 
     time_t lastsave;                /* Unix time of last successful save */

    还有一个定时器默认100毫秒来检测是否满足save条件的方法:serverCron

    int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData) 

    四、RDB文件结构 

      | REDIS | db_version | database | EOF | check_sum |

      RDB文件开头是REDIS,来判定是否是RDB文件。

      db_version  版本号

      databse 包含任意多个数据库(键值对)

      EOF RDB文件结束标志

      check_sum  校验长度

    AOF 持久化

    一、命令持久化,保存redis 的写命令

    二、命令追加

      redis 执行完写命令,将命令按照一定协议格式追加到 aof_buf 缓冲区

    sds aof_buf;      /* AOF buffer, written before entering the event loop */

    三、AOF文件写入与同步

      resid 服务器进程是一个事件循环

      文件事件:接受命令和输出内容

      时间事件:负责定时任务

      文件事件执行写命令,这样会追加命令到aof_buf 缓冲区,在这写命令结束之前会调用flushAppendOnlyFile 函数判断是否从缓冲区回写到AOF文件。

      写入策略有三个:

        always: 将aof_buf 缓冲区所有内容写入并同步到AOF文件。

        everysec(默认): 将缓冲区内容写入,超过一秒钟,并进行同步。

        no: 将缓冲区的所有内容同步,但是不同步。

    四、AOF 载入以及数据还原

      1、创建一个伪客户端

      2、分析aof文件 并解析一条命令

      3、伪客户端执行此命令

      4、循环执行2和3

    五、AOF重写

      AOF 存储写命令,体积会膨胀,恢复数据库的时间也会变长。

      新建文件AOF ,去除冗余命令,合并命令。达到缩减文件目的。

    六、AOF后台重写

      处理命令请求会因为这个aof重写造成阻塞。

      另起一个子进程,进行aof重写。但是会存在数据不一致的问题,子进程在处理重写一条命令后,同时主进程依然在写当操作对象的命令。造成数据不一致。

      解决方案:开辟aof重写缓存区

      命令会直接写入aof缓存区和aof重写缓存区,这样可以读取缓存区命令进行处理。类似队列,先写入队列进行待处理。

      生成的写命令-->aof缓冲区  -->写入同步到aof文件 

      生成的写命令-->aof重写缓冲区 -->  写完  -->发送信号给父进程 --> aof重写缓冲区写入新aof文件 -->原子覆盖旧aof文件

      

      父进程处理命令,保存aof,使用子进程,覆盖重写aof,达到性能最佳不阻塞,同时生成的新aof也是比较小。

  • 相关阅读:
    Python2的object和type
    str函数
    关于Python IDLE reload(sys)后无法正常执行命令的原因
    str和unicode类
    https://www.zhihu.com/question/31110175
    Python 头部 #!/usr/bin/python 和 #!/usr/bin/env 的区别
    正则表达式
    StringBuffer类
    String类
    抽象类、接口作为方法返回值和参数
  • 原文地址:https://www.cnblogs.com/sunchong/p/8358287.html
Copyright © 2020-2023  润新知