Redis 的 RDB(Redis DataBase)持久化是通过创建某个时间点的数据快照到磁盘上,以此来实现数据的持久保存。以下是关于Redis RDB持久化的关键源码解析要点:
核心流程
-
触发机制:RDB的触发可以通过配置自动执行(如满足一定条件下的键改变次数),也可以通过手动执行
SAVE
或BGSAVE
命令。自动触发基于redis.conf
中的save
指令配置,而BGSAVE
则在后台异步执行,不影响主线程处理命令。 -
数据快照:无论是
SAVE
还是BGSAVE
,最终都会调用到rdbSave()
函数来执行数据快照操作。在BGSAVE
的情况下,Redis会先通过fork()
系统调用创建一个子进程来执行快照生成,父进程继续处理客户端请求。 -
文件生成:
rdbSave()
内部会遍历Redis的字典,将数据库中的键值对序列化成特定格式的数据流,并写入到一个临时的RDB文件中。完成后,这个临时文件会替换掉旧的RDB文件,实现原子性更新。
关键数据结构与函数
- rdbSaveInfo:结构体,存储RDB保存过程中的各种信息,如开始时间、结束时间、文件大小等。
- rdbSave():核心函数,负责实际的RDB文件生成过程,包括键值对的遍历、序列化及文件写入。
- rio.c:Redis I/O库,提供了简化文件和网络I/O的接口,RDB的序列化过程大量使用了
rio
模块的功能。 - rdb.c:包含RDB持久化的主要实现逻辑,包括如何序列化各种数据类型到RDB格式。
实现细节
- Fork机制:在
BGSAVE
命令中,利用了Unix/Linux系统的fork()
机制来创建一个子进程。这样做的好处是主进程可以继续处理客户端请求,不会因为持久化操作而导致阻塞。 - 数据序列化:RDB文件格式包含了一系列Redis命令,用于在恢复时重新构建内存数据结构。序列化过程需要考虑到各种数据类型的特殊处理,例如过期时间、列表、集合等。
- 压缩与校验:RDB文件支持压缩选项,可以在生成时对文件进行压缩以节省空间。同时,RDB文件头部包含CRC64校验和,用于验证文件的完整性。
错误处理与恢复
- 错误处理:在RDB持久化过程中,Redis会监控写入操作的错误情况,并根据配置的
stop-writes-on-bgsave-error
来决定是否在出错时停止接收写请求。 - 数据恢复:Redis重启时,如果发现有效的RDB文件,会自动加载该文件来恢复内存中的数据结构,这一过程由
loadDatabaseFromDisk()
或类似逻辑完成。
深入阅读RDB持久化相关的源码,需要关注rdb.c
、rio.c
以及与之交互的其他核心模块,理解其数据遍历、序列化、文件操作和进程管理的具体实现。