Redis数据持久化
RDB
支持手工执行和服务端定期执行。持久化的内容为二进制数据文件
// server.h
struct redisServer {
……………………
// 保存 saveparams 数组
struct saveparam *saveparams; /* Save points array for RDB */
// 修改记录计数器,记录上一次成功执行 SAVE 或者 BGSAVE 后,数据进行了多少次修改(包括写入、删除、更新等操作)
long long dirty; /* Changes to DB from the last save */
// 上一次执行保存的时间,记录上一次成功执行 SAVE 或者 BGSAVE 的时间
time_t lastsave; /* Unix time of last successful save */
……………………
};
// server.h
struct saveparam {
// 执行的秒数
time_t seconds;
// 修改的次数
int changes;
// 只有在两个条件都满足的情况下,才会执行一次保存操作
// 具体配置为 save <seconds> <changes> (redis.conf)
};
AOF
AOF:Append Only File。通过记录 Redis 命令来记录数据库的变更
客户端——> Redis 服务器 ——> 执行命令 ——> 保存执行的命令 ——> AOF 文件
// server.h
struct redisServer {
…………………………
sds aof_buf; /* AOF buffer, written before entering the event loop */
…………………………
};
aof_buf :在 redis.conf 中配置 AOF ,开启 AOF,每次执行完命令,就会把命令写入到 aof_buf 中。
AOF 备份流程:
-
处理命令请求和响应
-
处理时间事件(
Server Cron函数) -
判断是否要写入
AOF(具体由配置决定) -
将
aof_buf中的内容写入到磁盘中具体流程:

-
appendfsync always将
aof_buf中的内容写入并且同步到AOF文件中,真正把指令存入了磁盘。优点:数据不会丢失
缺点:效率低
-
appendfsync everysec将
aof_buf中的内容写入到AOF文件。上次同步时间距离现在时间超过 1 s,则执行AOF同步 -
appendfsync no
将aof_buf中的内容写入到AOF文件。但是不对AOF同步,由操作系统决定
AOF恢复流程:
-
创建一个伪客户端
-
读取
AOF文件中的命令数据,依次执行 -
当所有命令都被执行完成时,流程结束
具体流程:

操作系统层面写入与同步:
-
调用系统函数
write,将内容写入到操作系统缓冲区 -
操作系统决定何时将缓冲区内的数据写入到磁盘
具体流程如下所示:
AOF 重写
AOF 存在的缺陷:
AOF越来越大,造成空间的浪费,数据加载也会非常慢- 多条执行的命令,有很大的几率都是多余的
解决方案:
-
AOF重写:通过读取Redis中存在的键的值,转换为对应的Redis命令再保存到AOF文件中// 比上次重写后的比例增加了 100% auto-aof-rewrite-percentage 100 // 并且 aof 文件体积超过 64mb 的情况下,才会发生重写 auto-aof-rewrite-min-size 64mb通过
fork一个子进程进行AOF重写。使得主进程不会被阻塞针对数据不一致的情况,
Redis设置了一个AOF重写缓冲区,子进程在建立时会使用该缓冲区内的内容。具体流程如下:

-
首先判断是否满足重写
AOF的条件,如果不满足,那么执行一般的AOF写入,将输入的命令保存到AOF缓冲区,再进行进一步的写入磁盘操作 -
如果满足重写
AOF的条件,那么就执行AOF重写。此时主进程将会fork一个子进程,让子进程完成重写的操作。 -
然而
fork子进程之后主进程依旧要接收命令,因此在fork一个子进程之后将会创建一个AOF重写缓冲区,将fork子进程之后的所有命令都会写入到这个缓冲区。 -
当子进程完成
AOF的重写任务之后,将会给主进程发送一个信号,使得主进程将AOF重写缓冲区内的内容添加到子进程写入的新的AOF文件中 -
最后使用新的
AOF文件替换掉旧的AOF文件,完成AOF的重写任务注意:在主进程处理子进程发送的信号和将
AOF缓冲区内容写入到新的AOF文件中的过程中,主进程是阻塞的

浙公网安备 33010602011771号