前面两篇文章介绍了Redis 的基本数据结构和Redis 的一些小功能,本片文章我们来来看Redis 的持久化。
Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化。
Redis 持久化方式
- 快照(RDB)
- AOF 日志
快照
RDB 持久化是将当前进程的数据生成快照写入磁盘的过程
-
触发机制
- 手动触发: 命令行输入 bgsave
- 自动触发
- 在 redis.conf 文件中试用save配置,如
save m n
, 表示 m 秒内存了 n 次修改时,自动触发bgsave - 默认情况下关闭(杀掉) Redis 进程,没有开启 AOF 持久化,会自动触发bgsave
- 在 redis.conf 文件中试用save配置,如
-
流程说明
- 1)执行 bgsave 命令,Redis 父进程判断当前是否存在正在执行的子进程(如:RDB/AOF 子进程),如果存在则直接返回
- 2)父进程执行 fork 操作创建子进程,fork 操作过程中父进程会被阻塞。(通过info stats 命令的latest_fork_uses 选项,可以获取最近一次fork操作的耗时,单位为微秒)
- 3)父进程 fork 完成后,bgsave 命令返回“Background saving started”信息后不再阻塞父进程。
- 4)子进程创建 RDB 文件,根据父进程内存数据生成临时快照文件,完成后对原文件进行原子替换。
- 5)进程发送信号给父进程表示完成,父进程更新统计信息(info Persistence 可查看)
-
优点:
- RDB 是一个紧凑压缩的二进制文件,体积小。很适合用于备份、传输。
- Redis 加载 RDB 恢复数据的速度远远快于 AOF 的方式。
-
缺点:
- RDB 方式数据没办法做到秒级持久化,因为bgsave每次运行都要
fork
创建子进程,属于重量级操作,频繁执行成本高。 - RDB 文件使用特定二进制格式保存,会存在老版本 Redis 服务器无法兼容新版本RDB格式的问题。
- RDB 方式数据没办法做到秒级持久化,因为bgsave每次运行都要
AOF 日志
AOF 持久化:以独立日志的方式记录每次写命令。
- 工作流程
- 命令写入
- 文件同步
- Redis 提供多种AOF缓存区同步文件策略,由参数 appendfsync 控制。
- always 每次写入都 fsync 到硬盘
- no 根据操作系统每次 fysnc 到硬盘
- everysec 每秒 fysnc 一次到硬盘,默认配置
- 重写机制
AOF 重写降低了文件的占有空间,同时更小的 AOF 文件可以更快被Redis 加载- 手动触发:命令行调用
bgrewriteaof
- 自动触发:根据
auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
参数配置触发auto-aof-rewrite-min-size
表示运行 AOF 重写时文件最小体积auto-aof-rewrite-percentage
代表当前文件空间和上一次重写后文件空间的比值。- 自动触发时机 =
aof_current_size
>auto-aof-rewrite-min-size
&& (aof_current_size
-aof_base_size
)/aof_base_size
>=auto-aof-rewrite-percentage
- 手动触发:命令行调用
- 重启载入
Redis 持久化文件加载流程如下:
混合持久化
Redis 4.0 添加了新的持久化方式–混合持久化。混合持久化混合就是结合 RDB 持久化和 AOF 持久化混合写入 AOF 文件。
- 设置:Redis 4 默认是关闭混合持久化的,可以通过
config set
设置配置参数aof-use-rdb-preamble- config get aof-use-rdb-preamble 获取混合持久化状态(yes 开启,no 关闭)
- config set aof-use-rdb-preamble yes
- redis.conf 中是没有 aof-use-rdb-preamble 配置的, 可以添加到其中,这样就不用每次重启后重新设置了
- 工作流程
- 主进程 fork 出子进程先将共享的内存副本全量的以RDB方式写入AOF文件
- 然后在将重写缓冲区的增量命令以AOF方式写入到文件
- 写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。也就是说新的AOF 文件前部分是RDB格式,后部分是AOF格式。
其他
- fork 操作
重写时,必不可少的是执行fork操作创建子进程,对于大多数操作系统来说fork是个重量及操作。如何改善fork操作的耗时那,可以从以下几个方面:- 优先使用物理机
- 控制Redis 实例的最大内存
- 降低fork 操作的频率
- AOF 追加阻塞
- 当开启 AOF 持久化时,常用的同步硬盘策略是everysec,用于平衡性能和数据安全性。对于这种方式,Redis 使用另一条线程每秒执行fysnc同步数据到硬盘,当系统硬盘资源繁忙是,会造成Redis主线程阻塞。
- 当开启 AOF 持久化时,常用的同步硬盘策略是everysec,用于平衡性能和数据安全性。对于这种方式,Redis 使用另一条线程每秒执行fysnc同步数据到硬盘,当系统硬盘资源繁忙是,会造成Redis主线程阻塞。