RDB
RDB(Redis Databases Background) Redis数据快照(二进制格式),将内存中的所有数据记录到磁盘中。Redis实例故障重启后可以从磁盘中读取快照文件,恢复数据。
- save:主进程来执行RDB,会阻塞所有命令
- bgsave:开启子线程来执行RDB,避免主进程受到影响
主动停机时会执行一次RDB
redis配置文件redis.conf
save 300 10:300秒内至少有10个key被修改,则执行bgsave
rdbcompression yes: 是否开启压缩(压缩会消耗cpu,不建议开启)
rdbchecksum yes: 是否开启数据校验(采用CRC64算法)
stop-writes-on-bgsave-error yes: 当启用RDB且最后一次后台报错数据失败,Redis是否停止接受数据
dbfilename dump.rdb: RDB文件名dump.rdb
dir ./: 文件保存路径
RDB流程
- fork主进程得到一个子进程,共享内存空间
- 自进程读取内存数据并写入到新的RDB文件
- 新的RDB文件覆盖旧的RDB文件
在写入RDB文件时,对数据进行了更新,fork中采用copy-on-write
- 当主进程执读操作,访问共享内存
- 当主进程执行写操作,则会拷贝一份数据,进行读写操作
在物理内存中存有一份自读数据,在对数据进行修改时,将数据拷贝一份到内存中,对拷贝的数据进行修改,读操作从自读的旧数据修改成新的数据
注意: 程序不能直接操作物理内存,只能操作逻辑内存,通过页表映射二者关系。
save和bgsave比较
命令 | save | bgsave |
IO类型 | 同步 | 异步 |
优点 | 不会消耗额外内存 | 不会阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要消耗额外内存 |
缺点
- RDB执行间隔时间长、二次RDB之间写入数据有丢失的风险
- fork子进程、压缩、写出RDB文件都是耗时操作
AOF
AOF(append Only File)追加文件,Redis处理的每一个写命令都记录在AOF文件,可以看做命令日志文件
redis配置文件redis.conf
appendonly yes:开启AOF,默认为no关闭
appendfilename "appendonly.aof":AOF文件名
appendfsync always/everysec/no:定义AOF写入频率。
- always:每执行一次写一次;
- everysec:先将命令放入AOF缓冲区,每一秒写一次;
- no:先将命令放入AOF缓冲区,由操作系统决定何时写
auto-aof-rewrite-percentage 100: aof文件比上次文件增长了多少百分比触发重写
auto-aof-rewrite-min 64mb: aof文件体积达到多少触发重写
AOF工作流程
AOF 持久化功能的实现可以简单分为 5 步:
- 命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
- 文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
- 文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
- 文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
- 重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
Linux 系统直接提供了一些函数用于对文件和设备进行访问和控制,这些函数被称为 系统调用(syscall)。
这里对上面提到的一些 Linux 系统调用再做一遍解释:
- write:写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘。虽然提高了效率,但也带来了数据丢失的风险。同步硬盘操作通常依赖于系统调度机制,Linux 内核通常为 30s 同步一次,具体值取决于写出的数据量和 I/O 缓冲区的状态。
- fsync:fsync用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回。
AOF 工作流程图如下:
来源: AOF工作流程
重写
多条写命令操作同一个key,会产生大量的命令,就会产生大量的冗余
解决: 通过bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令到达相同的结果
工作流程: 在AOF文件重写过程中,Redis会维护一个名为AOF重写缓冲区的特殊区域。这个缓冲区的主要任务是记录服务器在子进程创建新AOF文件的过程中执行的所有写入命令。当子进程完成新AOF文件的创建工作后,服务器将把重写缓冲区中的所有内容追加到新AOF文件的末尾。这一操作确保了新的AOF文件所保存的数据库状态与当前数据库的状态完全一致。在确认新AOF文件的内容和现有数据库状态一致后,服务器会用新AOF文件替换旧的AOF文件。这样,AOF文件的重写过程就完成了。
补充: AOF 重写(rewrite) 是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作
AOF和RDB比较
总结
参考文章: Redis · 语雀