- 前言
- 1. RDB 持久化
- 1.1 RDB 文件的创建与载入
- 1.2 自动间隔性保存
- 1.2.1 设置保存条件
- 1.2.2 dirty 计数器和 lastsave 属性
- 1.2.3 检查保存条件是否满足
- 1.3 RDB 文件
- 1.3.1 RDB 的文件结构
- 1.3.2 database 的文件结构
- 1.3.3 key_value_pairs 的文件结构
- 1.3.4 value 的编码
- 1.4 RDB 文件的示例
- 2 AOF 持久化与 RDB 持久化的区别
- 3. AOF 持久化
- 3.1 AOF 持久化的实现
- 3.2 AOF 文件的载入与数据还原
- 3.3 AOF 重写
- 3.4 AOF 后台重写
- 最后
前言
参考资料:《Redis设计与实现 第二版》;
第二部分为单机数据库的实现,主要由以下模块组成:数据库、持久化、事件、客户端与服务器;
本篇将介绍 Redis 中的持久化技术,主要有两种:RDB持久化和AOF持久化;
1. RDB 持久化 1.1 RDB 文件的创建与载入
- Redis使用 SAVE 和 BGSAVE 命令生成 RDB 文件;
- SAVE:会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止,阻塞期间服务器不能处理任何命令请求;
- BGSAVE:会派生一个子进程,由指进程负责创建 RDB 文件,父进程继续处理命令请求。BGSAVE 执行期间,会发生以下特殊情况:
- 在 BGSAVE 命令执行期间,客户端发送 SAVE 和 BGSAVE 命令会被服务器拒绝,防止产生竞争条件。客户端发送 BGREWRITEAOF 命令会被延迟;
- 在 BGREWRITEAOF 命令执行期间,客户端发送 BGSAVE 命令会被服务器拒绝;
- 创建 RDB 文件由 rdb.c/rdbSave 函数完成;
- 载入 RDB 文件由 rdb.c/rdbLoad 函数完成;
- RDB 文件的载入工作是在服务器启动时自动执行,只要 Redis 服务器在启动时检测到 RDB 文件存在,就会自动载入 RDB 文件;
- AOF 文件的更新频率通常比 RDB 文件更新频率高:
- 当服务器开启了 AOF 持久化功能时,会优先使用 AOF 文件还原数据库状态;
- 当服务器关闭了 AOF 持久化功能时,才会使用 RDB 文件来还原数据库状态;
- 服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止;
1.2 自动间隔性保存 1.2.1 设置保存条件
-
服务器会根据 save 选项所设置的保存值,设置服务器状态 redisServer结构的 saveparams 属性;
-
redisServer 的结构定义:
struct redisServer{ //... //记录了保存条件的数组 struct saveparam *saveparams; // } -
saveparams 属性是一个数组,每个 saveparam 结构保存了一个 save 设置的保存条件;
-
saveparam 的结构定义:
struct saveparam{ //秒数 time_t seconds; //修改值 int changes; }
-
dirty 属性和 lastsave 属性在 redisServer 结构体里:
struct redisServer{ //... //修改计数器 long long dirty; //上一次执行保存的时间 time_t lastsave; };- dirty 计数器记录距离上一次成功执行 SAVE 命令或者 BGNAME 命令之后,服务器对数据库状态进行了多少次修改;
- lastsave 属性是一个 UNIX 时间戳,记录了服务器上一次成功执行 SAVE 命令或 BGSAVE 命令的时间;
- Redis 的服务器周期性操作函数 serverCron 默认每隔 100ms 会执行一次,其中包括检查 save 选项所设置的保存条件是否满足(遍历并检查 saveparams 数组中的所有保存条件),满足则执行 BGSAVE 命令;
1.3 RDB 文件 1.3.1 RDB 的文件结构
-
RDB 文件结构的逻辑图:
-
各个字段含义:
字段 长度 储存值 说明 REDIS 5字节 “REDIS” 在载入文件时,快速检查所载入的文件是否为 RDB 文件 db_version 4字节 字符串表示的整数 RDB 文件的版本号 databases 0个或任意多个数据库,以及数据库中的键值对数据 EOP 1字节 EOP 常量 表示 RDB 文件正文内容的结束 check_sum 8字节 无符号整数 前4个部分的校验和
- database 为 RDB 文件的结构组成部分;
- databases 部分的逻辑结构:
-
各字段含义:
字段 长度 存储值 说明 SELECTDB 1字节 常量 表示接下来读入数据库号码 db_number 1、2或5字节 数字 表示数据库号码 key_value_pairs 长度不定 数据库所有的键值对数据
- key_value_pairs 为 databases 的结构组成部分;有两种类型,一种不带过期时间,一种带过期时间;
- key_value_pairs 部分的逻辑结构:
-
各字段含义:
字段 长度 存储值 说明 EXPIRETIME_MS 1字节 数值 表示过期时间 ms 8字节 数值 以毫秒为单位的 UNIX 时间戳 TYPE 1字节 常量 代表一种对象类型或底层编码 key 长度不定 字符串对象 表示键对象 value 长度不定 各种对象 表示值对象
- value 为 key_value_pairs 的结构组成成分;
- value 值对象的结构和长度会根据 TYPE 类型的不同而不同;
- value可以是字符串对象、列表对象、集合对象、哈希表对象、有序集合对象、INTSET编码的集合和ZIPLIST编码的列表、哈希表或有序集合;
- value的格式与编码对应请见 《第3章 对象》1.1 对象的定义;
- 字符串对象的格式与示例:
- 字符串对象可分为:压缩字符串和无压缩字符串两种:
- 列表与集合对象的格式:
- 哈希表对象的格式:
- 有序集合对象的格式:
-
INTSET 编码集合的格式:
- 将整数集合转换成字符串即可;
-
ZIPLIST编码的列表、哈希表或有序集合的格式:
- 将压缩列表转换成一个字符串对象,然后再保存到 RDB 文件;
1.4 RDB 文件的示例
-
不包含任何键值对的 RDB 文件:
REDIS标识 db_version EOF标识 check_num REDIS 0006 377 334 263 c 360 z 334 362 v -
包含字符串键的 RDB 文件:
REDIS标识 db_version SELECTDB db_number,0 号数据库 TYPE, 表示字符串 key value EOF标识 check_num REDIS 0006 376


