一、持久化
Redis支持RDB和AOF两种持久化机制持久化功能有效地避免因进程退出造成数据丢失问题, 当下次重启时利用之前持久化的文件即可实现数据恢复。
二、RDB
RDB 持久化是把当前进程数据⽣成快照保存到硬盘的过程,触发 RDB 持久化过程分为手动触发和
自动触发。
2.1触发机制
手动触发分别对应save和bgsave命令:
1.save命令:阻塞当前Redis服务器,知道RDB过程完成为止,对于内存比较大的实例造成长时间阻塞,基本不采用。
2.bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
Redis内部的所有涉及RDB的操作都采用类似bgsave的方式。
除了手动触发之外,Redis运行自动触发RDB持久化机制,这个触发机制才是在实战中有价值的。
1.使用save配置。如“save m n”表示在m秒内数据集发生了n次修改,自动RDB持久化。
2.从节点进行全量复制操作时,主节点自动进行RDB持久化,随后将RDB文件内容发送给从节点。
3.执行shutdown命令关闭Redis时,执行RDB持久化
2.2流程说明
bgsave是主流的RDB持久化方式,下面是它的运行流程:
1. 执行 bgsave 命令,Redis 父进程判断当前进是否存在其他正在执行的子进程,如 RDB/AOF 子进程,如果存在 bgsave 命令直接返回。
2. 父进程执行 fork 创建⼦进程,fork 过程中⽗进程会阻塞,通过 info stats 命令查看latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒。
3. 父亲进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞父进程,可以继续响应其他命令。
4. 子进程创建 RDB ⽂件,根据父亲进程内存⽣成临时快照⽂件,完成后对原有⽂件进行原子替换。执行 lastsave 命令可以获取最后⼀次⽣成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选项。
5. 进程发送信号给父进程表示完成,父进程更新统计信息。
2.3RDB文件的处理
保存:RDB 文件保存再 dir 配置指定的目录(默认 /var/lib/redis/)下,文件名通过 dbfilename
配置(默认 dump.rdb)指定。可以通过执行 config set dir {newDir} 和 config set dbfilename
{newFilename} 运行期间动态执行,当下次运行时 RDB 文件会保存到新目录。
压缩:Redis 默认采用 LZF 算法对⽣成的 RDB 文件做压缩处理,压缩后的文件远远小于内存大
小,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。
虽然压缩 RDB 会消耗 CPU,但可以大幅降低文件的体积,方便保存到硬盘或通过网络发送到
从节点,因此建议开启。
校验:如果 Redis 启动时加载到损坏的 RDB 文件会拒绝启动。这时可以使用 Redis 提供的 redis-
check-dump 工具检测 RDB 文件并获取对应的错误报告。
2.4RDB的优缺点
RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每 6 小时执行 bgsave 备份,并把 RDB 文件复制到远程机器或者文件系统中(如 hdfs)用于灾备。
Redis 加载 RDB 恢复数据远远快于 AOF 的方式。
RDB 方式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运行都要执行 fork 创建子进程,属于重量级操作,频繁执行成本过高。
RDB 文件使用特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有风
险。
三、AOF
AOF(Append Only File)持久化:以独立日志的方式记录每次写命令,重启时再重新执行 AOF
文件中的命令达到恢复数据的目的。AOF 的主要作用是解决了数据持久化的实时性,目前已经是
Redis 持久化的主流方式。理解掌握好 AOF 持久化机制对我们兼顾数据安全性和性能非常有帮助。
3.1使用AOF
开启 AOF 功能需要设置配置:appendonly yes,默认不开启。AOF 文件名通过
appendfilename 配置(默认是 appendonly.aof)设置。保存目录同 RDB 持久化方式⼀致,通过 dir配置指定。AOF 的工作流程操作:命令写⼊(append)、⽂件同步(sync)、文件重写
(rewrite)、重启加载(load)

1. 所有的写⼊命令会追加到 aof_buf(缓冲区)中。
2. AOF 缓冲区根据对应的策略向硬盘做同步操作。
3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
4. 当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复。
3.2命令写入
AOF 命令写⼊的内容直接是文本协议格式。例如 set hello world 这条命令,在 AOF 缓冲区会追加如下文本:
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
此处遵守 Redis 格式协议,Redis 选择文本协议可能的原因:文本协议具备较好的兼容性;实现简单;具备可读性。
AOF 过程中为什么需要 aof_buf 这个缓冲区?Redis 使用单线程响应命令,如果每次写 AOF ⽂件都直接同步硬盘,性能从内存的读写变成 IO 读写,必然会下降。先写入缓冲区可以有效减少 IO 次数,同时,Redis 还可以提供多种缓冲区同步策略,让用户根据自己的需求做出合理的平衡。
3.3文件同步
Redis 提供了多种 AOF 缓冲区同步⽂件策略,由参数 appendfsync 控制,不同值的含义如表“
可配置值 | 说明 |
always |
命令写⼊ aof_buf 后调⽤ fsync 同步,完成后返回
|
everysec |
命令写⼊aof_buf 后只执行 write 操作,不进行
fsync。每秒由同步线程进行 fsync。
|
no |
命令写⼊ aof_buf 后只执⾏ write 操作,由 OS 控制
fsync 频率。
|
系统调用 write 和 fsync 说明:
write 操作会触发延迟写(delayed write)机制。Linux 在内核提供页缓冲区用来提供硬盘 IO 性
能。write 操作在写⼊系统缓冲区后立即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区
页空间写满或达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
Fsync 针对单个文件操作,做强制硬盘同步,fsync 将阻塞直到数据写入到硬盘。
配置为 always 时,每次写⼊都要同步 AOF 文件,性能很差,在⼀般的 SATA 硬盘上,只能支持⼤约几百 TPS 写⼊。除非是非常重要的数据,否则不建议配置。
配置为 no 时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失风险大增,除非数据
重要程度很低,⼀般不建议配置。
配置为 everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失 1 秒的数据。
3.5重写机制
随着命令不断写⼊ AOF,文件会越来越大,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂
件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF 文件。
重写后的 AOF 为什么可以变小?有如下原因:
进程内已超时的数据不再写⼊文件。
旧的 AOF 中的无效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版
本。
多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b
c。
较小的 AOF ⽂件⼀方面降低了硬盘空间占用,一方面可以提升启动 Redis 时数据恢复的速度。
AOF 重写过程可以手动触发和自动触发:
手动触发:调用 bgrewriteaof 命令。
自动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定自动触发时 机。
auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最小文件大小,默认为 64MB。
auto-aof-rewrite-percentage:代表当前 AOF 占用大小相比较上次重写时增加的比例。