Redis ⽀持 RDB 和 AOF 两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。
rdb (Redis database)
RDB 持久化是把当前进程数据⽣成快照保存到硬盘的过程,触发 RDB 持久化过程分为⼿动触发和⾃动触发。
触发机制
⼿动触发分别对应 save 和 bgsave 命令:
-
save 命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为⽌,对于内存⽐较⼤的实例造成⻓时间阻塞,基本不采⽤。
-
bgsave 命令:Redis 进程执⾏ fork 操作创建⼦进程,RDB 持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在 fork 阶段,⼀般时间很短。
Redis 内部的所有涉及 RDB 的操作都采⽤类似 bgsave 的⽅式。
除了⼿动触发之外,Redis 运⾏⾃动触发 RDB 持久化机制,这个触发机制才是在实战中有价值的。
- 使⽤ save 配置。如 “save m n” 表⽰ m 秒内数据集发⽣了 n 次修改,⾃动 RDB 持久化。
- 从节点进⾏全量复制操作时,主节点⾃动进⾏ RDB 持久化,随后将 RDB ⽂件内容发送给从结点。
- 执⾏ shutdown 命令关闭 Redis 时,执⾏ RDB 持久化。
流程说明
bgsave 是主流的 RDB 持久化⽅式,下⾯根据图 4-1 了解它的运作流程。
- 执⾏ 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 选项。
- 进程发送信号给⽗进程表⽰完成,⽗进程更新统计信息。
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} 动态修改。
- 校验:如果 Redis 启动时加载到损坏的 RDB ⽂件会拒绝启动。这时可以使⽤ Redis 提供的 redis-check-dump ⼯具检测 RDB ⽂件并获取对应的错误报告。
RDB 的优缺点
- RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每 6 ⼩时执⾏ bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中(如 hdfs)⽤于灾备。
- Redis 加载 RDB 恢复数据远远快于 AOF 的⽅式。
- RDB ⽅式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运⾏都要执⾏ fork 创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。
- RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险。