Redis 的RDB和AOF

RDB (redis database redis数据库快照)

触发命令

  1. SAVE
    1. 阻塞
  2. BGSAVE
    1. 另起子线程,不会阻塞
// redisServer 结构中包括属性saveParams-- 可以用来指定BGSAVE的执行时间
struct redisServer {
    //...
    struct saveParam *saveParams;
    //修改计数器
    long dirty;
    //上次执行保存的时间
    time_t lastSave;
    //...
}

struct saveParam{
    time_t seconds; //秒数
    int changes;    //修改次数
}

按照上面的结构体可以看出,我们可以根据秒数修改次数触发BGSAVE

save 900 1  ===> 900s内数据库执行了超过1次修改,触发BGSAVE

触发条件判断

 def serverCron(){
     for(saveParam in server.saveParams){
         //距离上次保存的时间间隔
         saveInterval = now - server.lastSave;
         
         if(server.dirty > saveParam.changes && saveInterval > saveParam.seconds){
             BGSAVE(); //执行BGSAVE
         }
     }
 }

AOF (append only file)

struct redisServer{
    //...
    //AOF缓冲区
    sds aof_buf;
    //...
}

redis会在执行命令后会将写命令加入aof_buf缓冲区中

Redis 服务器进程就是一个事件循环(loop)

def eventLoop():
    while true:
        //处理文件事件,接受命令并发送命令回复
        //期间写入操作会加入到aof_buf缓存中
        processFileEvents();
        
        //处理时间时间  执行serverCoron之类的定时运行的函数
        processTimeEvents();
        
        //判断是否需要将aof_buf中的内容写入和同步到AOF文件中
        flushAppendOnlyFile;

名称 含义
写入 调用write函数,操作系统通常会将内容暂时保存在内存缓冲区中
同步 缓冲区空间满了或者时间到了或者特殊设置情况下将缓冲区中的内容写入磁盘中
  • redis AOF写入和同步的时间配置
appendfsync选项值 写入行为
always 每次执行时都会讲aof_buf缓冲区内容写入并同步到AOF文件,
1. 效率低
2. 最安全,最多丢失一个eventLoop内产生的数据
everysec 会将aof_buf内容写入AOF中,如果上次同步时间超过1S就会做AOF文件的同步
no 会将aof_buf内容写入AOF中,但是何时进行同步需要依赖操作系统
1.执行效率最高
2.如果宕机,丢失的数据会是最多

AOF重写节约空间

AOF的意思是将写操作命令追加到AOF文件最后,难免会出现一个key反复被操作,就会出现很多冗余的命令,文件就会变得很大。

AOF重写就是按照当前数据库中的kv,重新生成一份AOF文件,那么不管中间出现过多少次的反复操作,在重写的AOF文件中,只会存在一条。做到节约空间

def aof_rewrite(new_aof_file_name):
    // 创建新的AOF文件
    f = createFile(new_aof_file_name);
    for db in redisServer.db:
        // 忽略空的db
        f.write_command("SELECT" + db.id)
        
        //遍历db中的键
        for key in db:
            //忽略过期的键
            if(key.is_expried):continue;
            
            //按照不同类型生成命令,写入新的文件中
            //......
            
            //如果key有有效期,重写过期命令
            if(key.have_expire_time()):
                rewrite_exire_time(key)
    
    // 关闭文件
    f.close()

AOF后台重写

AOF重写涉及到大量的写入操作,所以需要单独启动子进程进行操作

  1. 子进程进行AOF重写的时候,父进程还可以继续处理命令请求

问题:在子进程进行AOF重写的时候,父进程还在处理命令,那么AOF重写完成之后,还是会出现数据不一致

redis的处理方式是,定义一个AOF重写缓冲区,

在子进程进行AOF重写的时候,执行的写命令会被加入到这个AOF重写的缓冲区,在子进程完成AOF重写通知父进程后,父进程会将AOF重写缓冲区内容加入到新出现的这个AOF文件中

RDB和AOF

  1. RDB同步只能间隔着操作,AOF可以做到实时
  2. RDB文件会相对比较小,AOF如果没有重写会相对比较大
  3. 启动时如果AOF持久化功能是开启的,会优先载入AOF文件

你可能感兴趣的:(Redis 的RDB和AOF)