从入门到精通【Redis】理解Redis持久化
文章目录
- 📕1. RDB持久化机制
- ✏️1.1 触发机制
- ✏️1.2 bgsave 命令的执行流程
- ✏️1.3 RDB ⽂件的处理
- ✏️1.4 RDB机制的优缺点
- 📕2. AOF持久化机制
- ✏️2.1 快速开启AOF功能
- ✏️2.2 AOF 缓冲区同步⽂件策略
- ✏️2.3 AOF重写机制
- ✏️2.4 AOF重写流程
- 📕3. Redis重启数据恢复流程
特此注明 :
Designed By :长安城没有风
Version:1.0
Time:2025.09.25
Location:辽宁 · 大连
学习Redis持久化之前,我们先回顾一下MySQL数据库的四大特性,分别是原子性,一致性,持久性以及隔离性。Redis作为当下热门的高性能键值对数据库,持久性也是必不可少的,之前我们学习了Redis是将键值对存储在内存中,那它是怎么进行持久化存储的呢?Redis提供了RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。
📕1. RDB持久化机制
RDB(Redis DataBase) 持久化是把当前内存中的所有数据定期⽣成快照保存到硬盘的过程(如果后续Redis服务器重启就可以将快照中的数据恢复到内存中),触发 RDB 持久化过程分为⼿动触发和⾃动触发。
✏️1.1 触发机制
手动触发
程序员通过Redis客户端,执行特定命令,手动触发快照生成。
-
save命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为⽌,对于内存⽐较⼤的实例造成⻓时间阻塞(导致类似于keys*的效果),基本不采⽤。
-
bgsave命令:Redis 进程执⾏ fork 操作创建⼦进程 (并不是采用多线程),RDB 持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在 fork 阶段,⼀般时间很短(Redis 内部的所有涉及 RDB 的操作都采⽤类似 bgsave 的⽅式)。
自动触发
- 通过Redis配置文件,如 “save m n” 表⽰ m 秒内数据集发⽣了 n 次修改,⾃动 RDB 持久化。
- 执⾏ shutdown 命令(Redis中的一个命令)关闭 Redis 时,执⾏ RDB 持久化。
- Redis进行主从复制时,主节点也会自动生成RDB快照,然后把快照内容传输给从节点。
✏️1.2 bgsave 命令的执行流程
- 执⾏ bgsave 命令,Redis ⽗进程判断当前进是否存在其他正在执⾏的⼦进程,如 RDB/AOF ⼦进程,如果存在 bgsave 命令直接返回。
- ⽗进程执⾏ fork 创建⼦进程,fork 过程中⽗进程会阻塞,通过 info stats 命令查看
latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒。 - ⽗进程 fork 完成后,bgsave 命令返回 “Background saving started” 信息并不再阻塞⽗进程,可
以继续响应其他命令。 - ⼦进程创建 RDB ⽂件,根据⽗进程内存⽣成临时快照⽂件,完成后对原有⽂件进⾏原⼦替换(自始至终,RDB文件只有一个)。执⾏ lastsave 命令可以获取最后⼀次⽣成 RDB 的时间。
✏️1.3 RDB ⽂件的处理
保存
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文件是一个二进制的文件,虽然压缩 RDB 会消耗 CPU,但可以⼤幅降低⽂件的体积,⽅便保存到硬盘或通过⽹络发送到从节点。)
校验
如果 Redis 启动时加载到损坏的 RDB ⽂件会拒绝启动。这时可以使⽤ Redis 提供的 redischeck-dump ⼯具检测 RDB ⽂件并获取对应的错误报告。
✏️1.4 RDB机制的优缺点
优点
- RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每 6 ⼩时执⾏ bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中⽤于灾备。
- Redis 加载 RDB 恢复数据远远快于 AOF 的⽅式。
缺点
- RDB ⽅式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运⾏都要执⾏ fork 创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。
- RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛
险。
📕2. AOF持久化机制
AOF(Append Only File)持久化:以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏ AOF⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是Redis 持久化的主流⽅式。理解掌握好 AOF 持久化机制对我们兼顾数据安全性和性能⾮常有帮助。
✏️2.1 快速开启AOF功能
我们需要通过修改Redis配置文件开启AOF功能(修改为appendonly yes),AOF功能默认不开启(默认appendonly no)。
下图所示AOF工作流程
- 所有的写⼊命令会追加到 aof_buf(缓冲区)中。
- AOF 缓冲区根据对应的策略向硬盘做同步操作。
- 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。
- 当 Redis 服务器启动时,可以加载 AOF ⽂件进⾏数据恢复。
✏️2.2 AOF 缓冲区同步⽂件策略
之前我们学习了Redis 是使⽤单线程模型响应命令,那如果每次写 AOF ⽂件都直接同步硬盘,性能从内存的读写变成 IO 读写,一定会大幅度下降,所以Redis在 AOF 过程中提供了 aof_buf 缓冲区,并且Redis 还提供多种缓冲区同步策略,让用户根据⾃⼰的需求做出合理的平衡。我们可以在配置文件中修改参数appendfsync的值,根据不同的业务场景选择合适的缓存区文件同步策略。
可配置值 | 说明 |
---|---|
always | 每次写入缓冲区后直接写入 AOF 文件中 |
everysec(默认) | 写入缓冲区后,不进行同步。一秒后再进行写入 AOF 文件 |
no | 只执行 write 操作(也就是只缓存),由操作系统控制写入 AOF 文件的频率 |
- 配置为 always 时,每次写⼊都要同步 AOF ⽂件,性能很差,在⼀般的 SATA 硬盘上,只能⽀持⼤约⼏百 TPS 写⼊。除⾮是⾮常重要的数据,否则不建议配置。
- 配置为 no 时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失⻛险⼤增,除⾮数据重要程度很低,⼀般不建议配置。
- 配置为 everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失 1 秒的数据。
✏️2.3 AOF重写机制
随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件(较⼩的 AOF ⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动 Redis 时数据恢复的速度。)。
为什么重写可以减少AOF体积?
- 旧的 AOF 中的⽆效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版本。
- 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b c。
AOF 重写触发机制
-
手动触发:调⽤ bgrewriteaof 命令。
-
自动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定⾃动触发时机。
2.1 auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB。
2.2 auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例。
✏️2.4 AOF重写流程
-
执⾏ AOF 重写请求 (如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程正在执⾏ bgsave 操作,重写命令延迟到 bgsave 完成之后再执⾏。)
-
⽗进程执⾏ fork 创建⼦进程
-
重写
3.1 主进程 fork 之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。
3.2 ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改操作写⼊AOF 重写缓冲区中。 -
⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中。
-
⼦进程完成重写
5.1 新⽂件写⼊后,⼦进程发送信号给⽗进程。
5.2 ⽗进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF ⽂件中。
5.3 ⽤新 AOF ⽂件替换⽼ AOF ⽂件。