现在的位置: 首页 > 综合 > 正文

redis源代码分析——RDB数据文件之我想写一个DUL工具(下)

2013年07月03日 ⁄ 综合 ⁄ 共 1391字 ⁄ 字号 评论关闭

Jack:redis的数据是怎么存储到数据文件的呢?

我:你看一下rdb.c里的int rdbSave(char *filename) {...}函数。这个函数是redis存储的核心函数。你从这里能看出什么呢?

Jack:传入的参数是一个文件名,所以redis的数据存储是以文件为单位的,而不是以数据库block为单位的。

我:是的。那,为什么redis的数据存储不已文件为单位,而采用以数据库block为单位的方式呢?

Jack:不知道。

我:你回忆一下《redis源代码分析——内存管理与数据类型》,里面说过,redis的内存管理并没有采用Oracle两条链表的经典模式,而是采用了HASH TABLE的方式。在Oracle的两条链表里,挂的是buffer。一个buffer对应一个数据库block。redis既然没有挂buffer的地方又怎么会有block呢?

Jack:嗯。明白了。

我:另外,既然要存储数据,就必须要从db里取数据,为什么这个函数的参数没有db相关的信息呢?

Jack:额~你说说吧。

我:因为DB的相关信息在一个巨无霸全局变量里——server.db。它写的过程如下。

1、if (fwrite("REDIS0002",9,1,fp) == 0) goto werr;

2、 if (rdbSaveType(fp,REDIS_SELECTDB) == -1) goto werr;

3、if (rdbSaveObject(fp,o) == -1) goto werr;(这里需要先判断这个key的object是什么类型的)

4、重复第3部分,直到一个数据库的key都被写完。

5、fflush(fp);fsync(fileno(fp));fclose(fp);

你看下,在这个过程中,最关键的是什么?

Jack:最关键的是fwrite()函数,以及rdbSaveObject(fp,o)函数。

我:这里面有什么dump吗?

Jack:没有。

我:所以,我感到很难理解,当聊到数据块结构解析的时候,你会提到dump。所以,你需要做的是,回头去看《Unix环境高级编程》,那才是王道。里面都对二进制文件write()的详细说明。

Jack:好的。另外,我想了解下,rdbSaveObject()这个函数的关键是什么呢?

我:int rdbSaveObject(FILE *fp, robj *o) {...},这样明白了吧?

Jack:不是太明白。

我:看来你不是一个合格的程序猿,一个合格的程序猿是可以从一个函数定义里看出这个函数的精髓的。而它的精髓就在于robj *o,你思考一下也就明白了。

Jack:那我如果要写一个Oracle的dul,需要思考些什么呢?

我:你觉得呢?

Jack:1、知道Oracle的block是结构体定义是什么样子的。2、破译它的数据类型存储。3、整合出逻辑。

我:是的。要搞到Oracle的block的结构体定义大概有两种方法。1、从Oracle内部的朋友那里搞到internal的资料(不过,不一定能成功)。2、自己破解。

Jack:如何破解呢?

我:不想告诉你。

Jack:为什么要破译Oracle的数据类型存储呢?

我:你看下int rdbSaveObject(FILE *fp, robj *o) {...}就明白了。如果你不看,我怎么说都没有用。

Jack:了解了。

我:这三点里,最难的是第2点,工作量最大的是第3点。感兴趣就去写一个吧。

抱歉!评论已关闭.