数据库状态:服务器中的非空数据库以及他们的键值对统称为数据库状态。
因为 Redis 是内存数据库,它将自己的数据库状态存储在内存里面,所以如果不想办法将存储在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据也会消失不见。为了解决这个问题, Redis 提供了 RDB 持久化功能, 可以将 Redis 在内存中的数据库状态保存到磁盘里面, 避免数据意外丢失。
因为 RDB 文件是保存在硬盘里面的, 所以即使 Redis 服务器进程退出, 甚至运行 Redis 服务器的计算机停机, 只要RDB 文件仍然在, Redis 服务器就可以用它来还原数据库状态。
RDB 文件的创建与载入
有两个 Redis 命令可以用于生成 RDB 文件, 一个是 SAVE, 另一个是 BGSAVE。
- SAVE 命令会阻塞 Redis 服务器进程,知道 RDB 文件创建完毕为止。
- BGSAVE 会派生出一个子进程,由子进程负责创建 RDB 文件, 服务器进程(父进程)继续处理命令请求;
与创建不同的是,RDB文件的载入是在服务器启动时自动执行的, 所以 Redis 并没有专门用于载入 RDB 文件的命令,只要 Redis 服务器在启动时检测到 RDB 文件的存在,他就会自动载入RDB文件。
值得一提的是,因为 AOF 文件的刷新频率通常比 RDB 文件的高, 所以如果服务器开启了 AOF 持久化功能, 那么服务器会优先使用 AOF 来还原数据库状态。
??SAVE 、BGSAVE命令执行和RDB文件载入时的服务器状态
SAVE 命令正在执行时,客户端发送的所有请求都会被拒绝。
因为 BGSAVE 的保存工作是由子进程执行的,所以期间 Redis 服务器仍然可以继续处理客户端的命令请求。但是,在 BGSAVE 命令执行期间服务器处理 SAVE, BGSAVE, BGREWRITEAOF 三个命令的方式会和平时有所不同。
- BGSAVE 命令执行期间,客户端发送的 SAVE 命令会被服务器拒绝。避免父进程和子进程同时执行两个 rdbSave 调用,防止产生竞争条件。
- BGSAVE 命令执行期间,客户端发送的 BGSAVE 命令会被服务器拒绝。因为两个 BGSAVE 命令也会产生竞争条件。
- BGSAVE 命令正在执行,那么客户端发送的 BGREWRITEAOF 命令会被延迟到 BGSAVE 命令执行完毕之后执行。反之亦然。原因是出于性能方面的考虑。
服务器在载入 RDB 文件期间,会一直处于阻塞状态,知道载入工作完成位置。
RDB 文件结构
一个完整 RDB 文件所包含的各个部分如下:
RDB文件结构
REDIS | db_version | databases | EOF | check_sum |
- db_version 长度为 4 个字节,它的值是一个字符串表示的整数,记录了 RDB?文件的版本号。RDB文件的最开头是 REDIS 部分,这个部分的长度为 5 字节,保存着 "REDIS" 五个字符。通过这五个字符,程序可以在载入时快速检查所载入的文件是否 RDB 文件。
- databases 部分包含着零个或任意多个数据库,以及各个数据库中键值对数据;若服务器的数据库状态为空,那么这部分也为空,长度为 0 字节。
- EOF常量的长度为1字节,标志着RDB文件正文内容的结束,程序读到这说明所有键值对都已载入完成。
- check_sum 是一个 8 字节长的无符号整数, 保存着一个校验和。检查 RDB 文件是否出错。
databases 部分
一个 RDB 文件的 databases 部分可以保存任意多个非空数据库。例如,如果 0 号数据库和 3 号数据库非空,则 RDB 文件如下所示
带有两个非空数据库 的RDB 文件示例
REDIS | db_sversion | databases 0 | databases 3 | EOF | check_sum |
其值每个非空数据库又可以表示为一下三部分:
RDB 文件中的数据库结构
SELECTDB | db_number | key_value_pairs |
- ?SELECTDB 常量的长度为 1 字节,表示接下来要读入的是一个数据库号码;
- db_number 保存着一个数据库号码,根据号码大小不同,长度可能是1字节、2字节或5字节。
- key_value_pairs 部分保存了数据库中的所有键值对数据
key_value_pairs部分
RDB 文件的每个 key_value_pairs 部分都保存了一个或以上数量的键值对,如果键值对带有过期时间,那么键值对的过期时间也会被保存在内。
不带过期时间的键值对由以下三部分组成:
其中TYPE记录了 value 的类型, 长度为 1 个字节,值可以是以下的一个:
- REDIS_RDB_TYPE_STRING
- REDIS_RDB_TYPE_LIST
- REDIS_RDB_TYPE_SET
- REDIS_RDB_TYPE_ZSET
- REDIS_RDB_TYPE_HSAH
- REDIS_RDB_TYPE_LIST_ZIPLIST
- REDIS_RDB_TYPE_SET_INTSET
- REDIS_RDB_TYPE_ZSET_ZIPLIST
- REDIS_RDB_TYPE_HASH_ZIPLIST
带有过期时间的键值对由以下五部分组成:
带有过期时间的键值对
EXPIRETIME_MS | ms | TYPE | key | value |
|