Redis的持久化存储——RDB

众所周知redis的持久化有AOF和RDB两种方式,其中AOF类似于操作日志的方式保存数据,即所有的数据都是基于现有的操作纪录进行优化保存,文件体积相对较大,但可读性较好,理论上可以通过管道直接导入redis。相对RDB格式的生成较为复杂,是将某一个时间节点上的内存镜像的优化映射。

记得有这么一种说法是“内存是新时代的硬盘,硬盘是新时代的磁带。”Redis的RDB文件生成过程是这个理论的最优化实践!配置文件中有一个对应的save A B选项,配置的就是如果在A秒内B个键值被修改,那么就会激活bgsave方法(就版本对应的是save方法)。bgsave命令是通过调用系统中级别的fork命令,克隆一个与现有进程。由于redis的单进程特性,这个过程也就意味着制造了一个当前内存数据的完整镜像,在子进程中启动持久化。对应的还有一个save命令,它的区别在于不fork进程,直接在主进程中持久化。尽管我本人认为fork是一个很笨拙的方式,而且有切身经历的灾难,单我仍然认为这是一个代价最为低廉的方式。

上图是一个简单的rdb文件,正常情况下有几个部分组成:

  • REDIS识别号
  • 版本0002
  • db编号标志
  • db编号x00,从这个长度上看,理论上最大的切片数是xFF 总共256个
  • 数据主体
  • 下一个db编号标志+db编号
  • 下一数据主体
  • ……
  • EOF结束符

数据主体的结构,首先是根据设置失效时间与否,标记一个timestamp时间戳记,然后再根据数据类型以及对应的数据体的描述:

  • string: x00 + key长度+key + var 长度+var
  • list: x0A+链表长+key长+key+ var1长+var1 + var2长+var2+…
  • hash: x09 + key长+key+field1长+field 1 + var1长+var1 + field2长+field2+var2长+var2+…
  • set: x0B+ key长+key + var1长+var1+var2长+var2+…
  • sort set : x0C + key长+key + 排序+var1长+var1 + x03xC0 + score 1 +var2长+var2+x03xC0 + score2+…

对于数据主体的描述中长度的描述,rdb文件在打开了rdbcompression选项后,会对数据进行压缩存储,具体的压缩方式我个人觉得有点像UTF-8的字符编码格式。

int rdbSaveLen(FILE *fp, uint32_t len) {
    unsigned char buf[2];
    int nwritten;

    if (len < (1<<6)) {
        /* Save a 6 bit len */ 6bit以下,用单个字节表示
        buf[0] = (len&0xFF)|(REDIS_RDB_6BITLEN<<6);
        if (rdbWriteRaw(fp,buf,1) == -1) return -1;
        nwritten = 1;
    } else if (len < (1<<14)) {
        /* Save a 14 bit len */ 6~14个bit, 用01前导的2个字节表示
        buf[0] = ((len>>8)&0xFF)|(REDIS_RDB_14BITLEN<<6);
        buf[1] = len&0xFF;
        if (rdbWriteRaw(fp,buf,2) == -1) return -1;
        nwritten = 2;
    } else {
        /* Save a 32 bit len */ 14~32个bit, 用10前导的总共5个字节表示
        buf[0] = (REDIS_RDB_32BITLEN<<6);
        if (rdbWriteRaw(fp,buf,1) == -1) return -1;
        len = htonl(len);
        if (rdbWriteRaw(fp,&len,4) == -1) return -1;
        nwritten = 1+4;
    }
    return nwritten;
}

大致上就这么多,下一步打算通过rdb的文件做一个基于db的切分迁移工具。

推荐阅读:
之前接触到的基于LAMP平台的
对于网站来说,琐碎文件是一个很
作为MySQL对于Web应用的
碰到一个悲催的事情:一台Red

发表评论

电子邮件地址不会被公开。 必填项已用*标注

请补全下列算式: *

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据