RDB
RDB 持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。RDB的文件的默认保存路径是服务器启动的当前目录,默认文件名为dump.rdb。
手动触发
手动触发分为 save命令 和bgsave命令,由于 save 命令会引起Redis阻塞,所以一般使用 bgsave。下图是 bgsave 触发RDB持久化的流程图:
- 首先父进程判断有没有正在执行中的 RDB 或 AOF 子进程,如果有则立马返回,没有则进行fork操作。
- fork操作会短暂的阻塞 Redis父进程。fork操作会创建一个子进程,
info stats
命令的latest_fork_usec
参数表示最近一个fork操作的耗时。 - 父进程fork完成后,bgsave命令返回
Background saving started
表示已经开始在生成RDB文件了,Redis父进程可以继续响应其他命令。 - 该子进程会根据 Redis父进程生成临时快照文件,完成后对原有文件进行原子替换。通过lastsave命令可以获取最后一次生成RDB的时间,对应 info 统计的
rdb_last_save_time
参数。 - 子进程发送信号给父进程表示完成。父进程更新统计信息。
可以通过 config set dir newdir
设置rdb文件保存的目录,config set dbfilename newFileName
设置生成的 RDB 文件名。
RDB 的优缺点
优点:RDB 是一个紧凑压缩的二进制文件,非常适用于备份,全量复制等场景。Redis 加载RDB恢复数据的速度也远远快于AOF。
缺点:RDB 方式数据没办法做到实时持久化/秒级持久化,bgsave运行每次都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。且有些版本的RDB格式是不一样的,不能兼容。
RDB的配置
RDB自动触发:
- 使用save相关配置,
save m n
,表示m秒内数据集存在n次修改时,自动触发bgsave。 - 从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点。
- 执行debug reload命令重新加载redis时,
- 默认情况下执行shutdown命令时,如果没有开启AOF持久化功能。则自动执行bgsave。
当在redis.conf配置
save ""
,将不会自动执行bgsage,保存路径通过dir参数指定,也可使用config set dir [newDir]
和config set dbfilename [newFilename]
指定持久化文件保存位置和文件名
AOF
AOF需要设置redis.conf:appendonly yes
,默认是不开启状态。文件名通过appendfilename
参数指定。保存目录与RDB方式设置一致,在redis.conf中通过dir参数指定。当开启了AOF时,redis服务启动会加载AOF持久化文件,不会加载RDB持久化文件。
AOF的工作流程操作分为:命令写入(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)。
流程如下:
- 所有写入命令会追加到
aof_buf
中。 - AOF缓冲区根据对应的策略向硬盘做同步操作。
- 随着AOF文件越来越大,需定期对AOF文件进行重写。
- 当redis服务器重启时,加载AOF文件进行数据恢复
AOF 文件同步策略
对于redis.conf的appendfsync
参数,该参数有下面这个三个值:
可配置值 | 说明 |
---|---|
always | 命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程返回。 |
everysec 默认配置值 | 命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次。 |
no | 命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘由操作系统负责,通常同步周期最长为30秒。 |
关于 write 和 fsync的说明
- write操作会触发延迟写机制。会将数据写入缓冲区后直接返回。同步文件之前,如果此时系统故障宕机,缓冲区内的数据会丢失。
- fsync针对单个文件,做强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证了数据的持久化。
AOF重写机制
随着命令不断写入AOF,文件会越来越大,Redis提供了AOF文件重写压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。更小的AOF文件意味着可以更快地被Redis加载。
为什么可以压缩文件体积,原因有以下几点:
- 进程内已经超时的数据不再写入文件。
- 如
set a 111
、set a 222
等类似命令,重写只会保留最终数据的写入命令。 - 多条写命令合并为一个,如
lpush list a
、lpush list b
等类似命令,合并为lpush list a b
。
AOF重写过程可以手动触发和自动触发:
- 手动触发:调用
bgrewriteaof
命令 - 自动触发:根据redis.conf中的
auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
参数自动触发时机:auto-aof-rewrite-min-size
:表示运行AOF重写时的文件最小体积,默认为64mb。auto-aof-rewrite-percentage
:代表当前AOF文件空间和上一次重写后AOF文件空间的比值。
重启加载
Redis持久化文件加载流程如下图所示:
文件校验
加载损坏的AOF文件时会拒绝启动,并打印如下日志:
# Bad file format reading the append only file: make a backup of your AOF file,then use ./redis-check-aof --fix <filename>
对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof- --fix命令进行修复,修复后使用diff -u对比数据的差异,找出丢失的数据,有些可以人工修改补全。
AOF文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全。可以通过redis.conf 配置 aof-load-truncated
配置来兼容这种情况,默认开启。