RDB、AOF持久化 &&混合持久化??
1.SAVE和BGSAVE命令可以用于生成RDB文件,SAVE会阻塞进程,BGSAVE会派生一个子进程(redisServer.rdb_child_pid),然后由子进程负责创建RDB文件
2.由于AOF文件的更新频率比RDB高,所以如果服务器开启了AOF,则优先加载AOF;否则加载RDB
3.由于BGSAVE命令可以在不阻塞服务器进程的情况下进行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令
serverCron函数周期性执行,遍历所有保存条件(redisServer.saveparams),只要有一个满足,服务器就会执行BGSAVE命令
struct redisServer {
int dirty; // 距离上次保存,所执行的修改操作次数
time32 lastsave; // 上次保存时间
pid_t rdb_child_pid; // 执行bgsave的子进程id
struct saveparam *saveparams; // 保存条件数组指针
int saveparamslen; // 保存条件数组长度
char* rdb_filename; // RDB文件名字
int rdb_compression; // 是否对RDB文件压缩
int rdb_checksum; // 是否对RDB文件校验
time32 lastbgsave_try; // 上次执行bgsave的时间
int lastbgsave_status; // 上次执行bgsave的结果:C_OK-成功,C_ERR-失败
}
AOF持久化功能分为:命令追加、文件写入、文件同步三个步骤
1.命令追加
如果AOF持久化功能处于打开状态时,服务器执行完一个写命令后,会议协议格式将该写命令追加到struct Server的成员aof_buf缓冲区的末尾
2.文件写入与同步
always aof缓冲区写入aof文件 同步
everysec aof缓冲区写入aof文件 如果间隔超过1s则同步,并且同步操作交给一个线程专门负责
no aof缓冲区写入aof文件 不同步,同步操作交给操作系统
注:写入aof文件就是指写入aof文件在内存中的缓冲,而同步则是由内存同步到硬盘。操作系统这样实现是为了提高效率
redis读取AOF文件并还原数据库状态的详细步骤:
1.创建一个不带网络连接的伪客户端,因为执行命令需要客户端上下文
2.逐一从AOF文件中读取写入命令并执行,直到所有写入命令都被处理完毕
AOF重写(使用子进程),AOF重写是将当前的服务器状态通过redis命令的形式保存到AOF文件中,是新建一个AOF文件,而不是真的重写AOF文件。该操作放在子进程里执行,可以达到两个目的:
1.子进程进行AOF重写期间,服务器进程可以继续处理命令请求
2.子进程带有进程的数据副本,使用子进程而不是子线程,可以在不使用锁的情况下,保证数据的安全性
在子进程进行AOF重写的过程中,父进程有可能执行了写入命令,这时AOF文件就与当前服务器状态出现不一致,解决方法:
创建一个AOF重写缓冲区,当子进程在进行AOF重写时,父进程每次执行写入命令不仅向AOF缓冲区写入,也向AOF重写缓冲区写入。当子进行进行完AOF重写创建完AOF文件时向父进程发送一个命令,父进程收到该信号时,首先将AOF重写缓冲区的数据写入该新创建的AOF文件,并将新AOF文件改名并原子的覆盖现有的AOF文件