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重写。
时间: 2024-10-28 02:09:35