redis是一个内存数据库,所有的数据以数据结构的形式保存在内存中。redis为了重启后使数据仍然可以使用,提供rdb和aof两种持久化方式。 在redis运行时,rdb程序就是将内存中的数据库的数据结构以rdb文件形式保存到磁盘;在redis重启时,rdb程序就通过载入rdb文件来还原重启前的数据库状态。
rdb的文件结构
一个rdb可以分为以下几个部分:
REDIS
文件最开头保存着REDIS五个字符,标志rdb文件的开始。
db_version
一个四字节的以字符表示的整数,记录了文件使用的RDB版本号
databases
存放了服务器上所有非空数据库的所有数据。databases的结构如下:
SELECTDB
一字节的常量,标示接下来要读的是一个数据库号码。
db_number
保存了一个数据库号码,使后面读入的键值对可以载入到正确的数据库中。
key_value_pairs
保存了键值对,如果键值对带有过期时间也保存在内。
不带过期时间的结构
带过期时间的结构
EOF
标志着数据库内容的结尾(不是文件的结尾)
CHECK_SUM
RDB 文件所有内容的校验和, 一个 uint_64t
类型值。REDIS 在写入 RDB 文件时将校验和保存在 RDB 文件的末尾,当读取时, 根据它的值对内容进行校验。
rdbSave和rdbLoad
rdbSave和rdbLoad是rdb中最核心的两个函数,rdbSave用于生成rdb文件持久化道磁盘,rdbLoad用于将rdb文件重新载入到内存还原数据库。
1、rdbSave的实现
int rdbSave(char *filename, rdbSaveInfo *rsi) {
……//创建rdb文件
snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
fp = fopen(tmpfile,"w");
rioInitWithFile(&rdb,fp);
if (rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi) == C_ERR)
……//同步文件到磁盘
if (fsync(fileno(fp)) == -1) goto werr;
……//重命名rdb文件
if (rename(tmpfile,filenam