redis是一种内存数据库,也就是redis的数据在正常工作的情况下都是存储在内存中。但并不是说redis只能把数据存储在内存中,redis提供了两种数据持久化机制:rdb和aof。rdb持久化有三种方式被启动:用户向redis发送save或者bgsave命令。save和bgsave的不同就在于save会阻塞redis服务器,而bgsave不会。这样bgsave就在不影响redis服务器正常工作的情况进行数据持久化,bgsave主要是通过子进程来进行数据持久化。无论是save还是bgsave最后都会通过调用rdbsave来进行保存操作。
在讲解rdbsave这个函数之前,先来介绍下rdb文件格式。一个rdb文件分为以下几个部分:
REDIS:文件的最开头保存着REDIS 五个字符,标识着一个RDB 文件的开始。
RDB-VERSION:一个四字节长的以字符表示的整数,记录了该文件所使用的RDB 版本号。目前的RDB 文件版本为0006 。
SELECT-DB:这域保存着跟在后面的键值对所属的数据库号码。在读入RDB 文件时,程序会根据这个域的值来切换数据库,确保数据被还原到正确的数据库上。
KEY-VALUE-PAIRS:每个键值对的数据使用以下结构来保存:
OPTIONAL-EXPIRE-TIME:,如果键没有设置过期时间,那么这个域就不会出现;反之,如果这个域出现的话,那么它记录着键的过期时间
KEY:保存着键,格式和REDIS_ENCODING_RAW 编码的字符串对象一样
TYPE-OF-VALUE:记录着VALUE 域的值所使用的编码,根据这个域的指示,程序会使用不同的方式来保存和读取VALUE 的值。
VALUE:保存着真实的值,但是这个被保存的值会被进行各种编码。(可以查看redis设计与实现)
关于rdb文件格式还可以参考博客:http://www.searchdatabase.com.cn/showcontent_59162.htm
下面来正式看下rdbsave函数:
int rdbSave(char *filename)
{
......
// 以 "temp-<pid>.rdb" 格式创建临时文件名
snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
fp = fopen(tmpfile,"w");
......
snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
if (rdbWriteRaw(&rdb,magic,9) ==