Redis - 持久化

Redis 分别提供了 RDB 和 AOF 两种持久化机制:

  • RDB 将数据库快照用二进制数据保存到磁盘
  • AOF 以协议文本的方式将对数据库的写入命令和参数保存在AOF文件中

RDB

拢共分两步,比把大象装冰箱还简单:

  • rdbSave() 保存到磁盘
  • rdbLoad,重启后加载还原

保存

save和bgsave命令都会保存,前者阻塞主进程,后者fork出子进程进行保存
SAVE时因为AOF写入时后台线程完成所以可以同步进行
BGSAVE时,进行SAVE或者是BGSAVE都会提示错误

还原

启动时就会还原,没还原一千条处理一次请求(只针对几个命令响应,其他返回错误),完全还原后才正常处理请求
因为AOF的频率更高,因此会优先使用AOF还原

AOF

开启AOF,然后客户端发起的所有修改请求都会被保存在AOF文件中

步骤

  • 命令传播 客户端发送修改请求,如果执行成功,则传播到AOF程序中
if(executeCommond(command, params) == SUCCESS){
    if(AOFOPEN){
        propagateAOF(command, params)
        if(replication){
            propagateReplicationAOF(command, params)
        }
    }
}
  • 缓存追加 AOF程序转化命令参数数据库Id等为Redis通讯协议格式,加到aof缓存末尾
  • 文件写入和保存 WRITE将缓存会写到AOF文件,或者SAVE将AOF文件写到磁盘

保存模式

对应Redis的配置

  • 不保存
    由主线程触发,WRITE和SAVE都会阻塞主线程。
    一般只会在Redis关闭时才会触发,因此性能好,但是安全性低,如果当机则会丢失数据
  • 每命令保存
    都阻塞
    但是安全性高,只会丢失一个命令,但是性能最差
  • 每时间段保存
    WRITE阻塞 SAVE由子进程完成,不阻塞。 执行时会根据条件判断是SAVE还是WRITE
    安全性及性能平衡

还原

还原模式很简单,创建伪客户端,读取AOF文件,依次执行命令

AOF重写

上面的还原会有个问题,比如一个list[1,2,3,4]插入[5,6]又删除[1,2]变成了[3,4,5,6]除了记录所有过程外,还可以转化为一个set[3,4,5,6]的命令。这种就可以大大减少AOF的体积,直接得到最后的状态

AOF后台重写

为了不阻塞主进程,redis可以在后台重写AOF。
但是考虑到后台重写可能造成不一致的情况,整个重写过程如下:

exeCommand(){
    writeCommandToOldAofFile();
    writeCommandToReAofCache();
}

backendAof(){
    byte[] reAofCache = new byte[]; 
    File newAofFile = new File();
    writeCommandToNewAofFile();
    if(writeFinished){
        // 主线程中断
        // 主线程把reAofCache中的命令写到newAofFile中
        // 用新AofFile替换旧的AofFile
    }
}

大概的过程是,把耗时多的重新计算,写新文件等另起线程操作。 把这段操作时间内产生的新的状态变更记录到缓存中。 耗时操作完成后中断主线程,主线程把缓存中的内容再会写到新文件,用新文件代替老文件。这样就可以保证不丢数据,也能保证尽可能减少中断服务的时间

触发条件:
AOF开启时会维护三个变量:大小,最后一次AOF重写后的增长量,自后一次AOF重写后增长的百分比。
当大小超过临界值,且增长百分比超过临界值时就会执行AOF重写。

你可能感兴趣的:(Redis - 持久化)