Redis 提供了多种持久化机制,用于将数据保存到磁盘中,以防止因服务器重启或故障而导致的数据丢失。主要的持久化策略有两种:RDB (Redis Database) 和 AOF (Append Only File),即当 Redis 服务器重新启动时,会读取相应的文件,来还原上次退出时的数据;
一、RDB
RDB 是 Redis 默认的持久化方式,它会定期的将 Redis 内存中的所有数据都写入硬盘中,生成一个 "快照"——.rdb 二进制文件;
"定期" 又有两种方式:
1)手动触发
程序员通过 Redis 客户端,执行特定的命令(save,bgsave)来触发快照的生成;
- save 命令:执行 save 命令的时候,redis 就会全力以赴的进行 "快照生成" 操作,此时就会阻塞 redis 的其他客户端的命令,直到 RDB 过程完成为止,对于内存比较大的实例造成长时间阻塞,基本不采用;
- bgsave 命令:background,该命令不会影响 Redis 服务器处理其他客户端的请求和命令,该命令通过多进程的方式实现,Redis 进程执行 fork 操作创建子进程,RDB 持久化由子进程负责,完成后自动结束,阻塞只发生在 fork 创建进程阶段,这个时间很短;
- 执行 bgsave 命令,Redis 父进程判断当前进是否存在其他正在执行的子进程,如 RDB / AOF 子进程,如果存在,bgsave 命令会直接返回;
- 父进程执行 fork 创建子进程,fork 过程中父进程会阻塞,通过 info stats 命令查看 latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒;
- 父进程 fork 操作执行完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞父进程,此时父进程可以继续响应其他命令;
- 子进程创建 rdb 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换;执行 lastsave 命令可以获取最后一次生成 rdb 的时间,对应 info 统计的rdb_last_save_time 选项;
- 进程发送信号给父进程表示完成,父进程更新统计信息;
通过 save 命令 手动触发 RDB
通过 bgsave 命令手动触发 RDB
rdb 文件保存在 dir 配置指定的目录(默认 /var/lib/redis/)下,文件名通过 dbfilename 配置(默认 dump.rdb)指定,/user/bin/ 目录下有检测 rdb 文件的工具 redis-check-rdb,通过 redis-check-rdb rdb 文件名的方式检查 rdb 文件;
如果 Redis 启动时加载到损坏的 rdb 文件会拒绝启动,此时可以使用 Redis 提供的 redischeck-dump 工具检测 rdb 文件并获取对应的错误报告; 也可以通过查看 Redis 的日志查看错误问题,日志文件默认在 /var/log/redis/ 目录下;
通过 bgsave 生成 rdb 文件时,会把要生成的快照数据保存在一个临时文件中,当这个快照生成完毕之后,再删除之前的 rdb 文件,把新生成的临时文件名修改为删除的 rdb 文件名(可通过 stat 命令查看文件的 Inode 编号);
2)自动触发
在 Redis 的配置文件中可以看到这样的信息;
"save m n" 表示 m 秒内数据集发生了 n 次修改时,自动 RDB 持久化,既要满足经过 m 秒,还要满足达到 n 次修改;
以下情况也会自动触发 rdb
- 在 Redis 服务器关闭时也会自动触发
- Redis 进行主从复制的时候,主节点也会自动生成 rdb 快照,然后把 rdb 文件内容传输给从节点
3)RDB 的优缺点
优点
- 高效的磁盘IO:由于是定期生成快照,RDB 文件的磁盘 IO 操作相对集中,通常比 AOF 的每次写操作同步更加高效。
- 快速恢复:RDB 文件是一个紧凑的二进制文件,加载速度较快,适合用于快速数据恢复。
- 简单文件结构:RDB 文件结构相对简单,文件较小,便于传输和备份。
缺点
- 数据持久化的时间间隔:RDB 是基于时间间隔生成快照的,在两次快照之间的数据可能会丢失。如果 Redis 崩溃(通过 kill -9 杀掉 redis 进程),则最后一次快照之后的所有数据都将丢失,即不能实时的持久化保存数据。
- 生成快照时的性能开销:生成快照时,尤其是对大数据集生成快照,可能会对 Redis 的性能产生影响。
- 存在兼容性问题:Redis 版本演进过程中有多个 RDB 版本,兼容性可能有风险。
二、AOF
AOF 默认是关闭状态,需要修改配置文件(改为 yes)来开启 AOF 功能,当开启 AOF 的时候,RDB 就不生效了,即 Redis 启动时就不会读取 RDB 文件的内容了;同时 AOF 写入的是文本文件;
AOF 通过记录每个写操作的日志,以追加的方式写入日志文件,来实现数据持久化;
AOF 的主要作用是解决了数据持久化的实时性,目前已经是 Redis 持久化的主流方式;
1)AOF 工作流程
1. 所有的写入命令会追加到 aof_buf(缓冲区)中;
2. AOF 缓冲区根据对应的策略(缓冲区刷新策略)向硬盘做同步操作;
3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的;
4. 当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复;
可以看出 AOF 机制并非是直接让工作进程把数据写入硬盘,而是先写入一个内存的缓冲区,积累一波后,再统一写入硬盘,若在缓冲区还没来得及写入硬盘的时候,此时进程异常结束,主机掉电,则缓冲区的数据会丢失;
因此 Redis 给出了缓冲区的刷新策略(类似于 MySQL 的事务隔离级别),通过 appendfsync
选项进行配置,默认为 everysec,分别为:
- always:每次有写操作时,立即将数据写入 AOF 文件并同步到磁盘;
- everysec:每秒将缓冲区中的数据写入 AOF 文件并同步到磁盘,Redis 使用后台线程每秒执行一次
fsync
; - no:让操作系统决定何时将缓冲区中的数据写入 AOF 文件并同步到磁盘。Redis 只负责将数据写入缓冲区,不主动执行
fsync
;
2)AOF 的重写机制
随着命令不断写入 AOF,文件会越来越大,为了解决这个问题,Redis 引入 AOF 重写机制压缩文件体积;AOF 文件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF 文件;
重写后的 AOF 文件为什么可以变小?有如下原因:
- 进程内已超时的数据不再写入文件;
- 旧的 AOF 中的无效命令,例如 del、hdel、srem 等重写后将会删除,只需保留数据的最终版本;
- 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list c 从可以合并为 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 占用大小相比较上次重写时增加的比例;
-
AOF 重写流程
1. 执行 AOF 重写请求,如果当前进程正在执行 AOF 重写,则请求不执行;如果当前进程正在执行 bgsave 操作,则会等待 bgsave 操作完成之后再执行;
2. 父进程执行 fork 创建子进程;
3. 重写
- 父进程 fork 之后,可以继续响应其他命令,所有修改操作写入缓冲区并根据缓冲区策略同步到硬盘,保证旧的 AOF 文件机制正确;
- 父进程生成一个 aof_rewrite_buf 重写缓冲区,用于存放 fork 之后的写数据(这部分数据也会在 aof_buf 中存在);
4. 子进程根据内存快照,将命令合并到新的 AOF 文件中(精简旧的 AOF 文件);
5. 子进程完成重写
- 新文件写入后,子进程发送信号给父进程;
- 父进程把 AOF 重写缓冲区内临时保存的命令追加到新的 AOF 文件中;
- 用新的 AOF 文件替换旧的 AOF 文件;
3)AOF 的优缺点
优点
- 更高的数据安全性:AOF 可以配置为每次写操作后立即同步到磁盘或者每秒同步一次,从而提供不同程度的数据安全性,即使 Redis 崩溃,通过 AOF 文件可以恢复到最后一次写操作的状态(根据同步策略,数据丢失可以控制在最小范围内);
- 可读性:AOF 文件是一个纯文本文件,包含了所有写操作的记录,这使得它更容易阅读和理解;
缺点
- 性能开销:相比 RDB 快照,AOF 在每次写操作时都会进行磁盘写入,这可能会导致较高的 I/O 开销,尤其是在写操作频繁的场景中;
- 恢复速度:在 Redis 重启时,需要从 AOF 文件中重放所有的写操作来恢复数据,对于大型 AOF 文件,这个过程可能比较耗时,导致恢复速度较慢;
三、混合持久化
混合持久化结合了 RDB 和 AOF 两种持久化方式的优点,通过将 RDB 快照和 AOF 日志结合在一起,实现数据的高效持久性和快速恢复;
在 redis 配置文件中存在以下内容,表示是否开启了混合持久化(默认为 yes,表示开启);
优点:
- 快速恢复:相比纯 AOF 持久化,混合持久化大大加快了恢复速度,因为大部分数据直接从 RDB 快照加载。
- 高数据安全性:相比纯 RDB 持久化,混合持久化能确保更高的数据持久性,因为 AOF 日志记录了快照后的所有写操作。
- 文件体积:通过合并 RDB 和 AOF,减少了持久化文件的体积增长。