redis object对象系统的源码分析
来源:互联网 发布:Execl数据分析证书 编辑:程序博客网 时间:2024/05/01 19:19
redis中实现很多数据结构来存储键值对,主要有简单动态字符串、双端队列、字典、压缩列表、
整数集合和跳跃表。但是使用也是基于这些数据结构构建看一个对象系统,主要是字符串对象、列表
整数集合和跳跃表。但是使用也是基于这些数据结构构建看一个对象系统,主要是字符串对象、列表
对象、哈希对象、集合对象和有序集合对象,每种对象都用到至少一种上述的数据结构。
在object.c主要是实现了对象的创建、引用计数和释放,字符串对象的编码转换。
对象的结构体
typedef struct redisObject { unsigned type:4;//对象类型 unsigned encoding:4;//对象的编码类型 unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */ int refcount;//对象的引用计数 void *ptr;//指向对象内容的指针} robj;对象的五种类型
#define OBJ_STRING 0//字符串对象#define OBJ_LIST 1//列表对象#define OBJ_SET 2//集合对象#define OBJ_ZSET 3//有序集合对象#define OBJ_HASH 4//哈希对象对象的编码
#define OBJ_ENCODING_RAW 0//简单动态字符串——字符串对象#define OBJ_ENCODING_INT 1//long类型整数——字符串对象#define OBJ_ENCODING_HT 2//字典——散列对象和集合对象#define OBJ_ENCODING_ZIPMAP 3//压缩图#define OBJ_ENCODING_LINKEDLIST 4 //双端列表——列表对象#define OBJ_ENCODING_ZIPLIST 5 //压缩列表——有序集合对象#define OBJ_ENCODING_INTSET 6 //整数集合——集合对象#define OBJ_ENCODING_SKIPLIST 7 //跳跃表——有序集合对象#define OBJ_ENCODING_EMBSTR 8 //embstr编码的简单动态字符串——字符串对象#define OBJ_ENCODING_QUICKLIST 9 //基于压缩列表的双端列表——列表对象一、对象的创建
基本对象创建函数,创建robj结构体,指定类型和对象内容,编码初始化为OBJ_ENCODING_RAW,
泛化的对象创建函数需要重新设定自己的编码。
robj *createObject(int type, void *ptr) { robj *o = zmalloc(sizeof(*o)); o->type = type; o->encoding = OBJ_ENCODING_RAW; o->ptr = ptr; o->refcount = 1; /* Set the LRU to the current lruclock (minutes resolution). */ o->lru = LRU_CLOCK(); return o;}五种对象的创建函数
//根据字符串长度选择使用OBJ_ENCODING_EMBSTR还是OBJ_ENCODING_RAW创建字符串对象robj *createStringObject(const char *ptr, size_t len) { if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT) return createEmbeddedStringObject(ptr,len); else return createRawStringObject(ptr,len);}robj *createEmbeddedStringObject(const char *ptr, size_t len);//创建OBJ_ENCODING_EMBSTR编码的字符串对象robj *createRawStringObject(const char *ptr, size_t len);//封装createObject创建OBJ_ENCODING_RAW编码的列表对象robj *createQuicklistObject(void);//封装createObject创建OBJ_ENCODING_QUICKLIST编码的列表对象robj *createZiplistObject(void);//封装createObject创建OBJ_ENCODING_ZIPLIST编码的列表对象robj *createSetObject(void);//封装createObject创建OBJ_ENCODING_HT编码的集合对象robj *createIntsetObject(void);//封装createObject创建OBJ_ENCODING_INTSET编码的集合对象robj *createHashObject(void);//封装createObject创建OBJ_ENCODING_ZIPLIST编码的散列对象robj *createZsetObject(void);//封装createObject创建OBJ_ENCODING_ZIPLIST编码的有序集合对象robj *createZsetZiplistObject(void);//封装createObject创建OBJ_ENCODING_ZIPLIST编码的有序集合对象二、对象的引用计数和释放
对象的引用计数主要是为了更好的管理对象,及时的释放掉对象不用的内存。
void incrRefCount(robj *o) {//引用计数增加函数 if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++;}//引用计数减少函数void decrRefCountVoid(void *o) { decrRefCount(o);}//引用计数减少函数,当计数为1是调用,释放对象。void decrRefCount(robj *o) { if (o->refcount == 1) { switch(o->type) {//根据类型不同选择不同释放函数 case OBJ_STRING: freeStringObject(o); break; case OBJ_LIST: freeListObject(o); break; case OBJ_SET: freeSetObject(o); break; case OBJ_ZSET: freeZsetObject(o); break; case OBJ_HASH: freeHashObject(o); break; default: serverPanic("Unknown object type"); break; } zfree(o); } else { if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0"); if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--; }}//重置对象引用计数robj *resetRefCount(robj *obj) { obj->refcount = 0; return obj;}对象释放函数
void freeStringObject(robj *o); //释放字符串对象的内容,o->ptrvoid freeListObject(robj *o); //释放列表对象的内容,o->ptr void freeSetObject(robj *o); //释放集合对象的内容,o->ptr void freeZsetObject(robj *o); //释放有序集合对象的内容,o->ptrvoid freeHashObject(robj *o);//释放散列对象的内容,o->ptr三、对象的编码转换
//对字符串对象进行节省空间的编码转换robj *tryObjectEncoding(robj *o) { long value; sds s = o->ptr; size_t len; //OBJ_ENCODING_INT编码的对象不需要编码转换 if (!sdsEncodedObject(o)) return o; //引用计数大于1的字符串对象不能进行编码转换 if (o->refcount > 1) return o; len = sdslen(s); if (len <= 21 && string2l(s,len,&value)) { //内容为长度小于21的数字字符串的字符串对象 if ((server.maxmemory == 0 || (server.maxmemory_policy != MAXMEMORY_VOLATILE_LRU && server.maxmemory_policy != MAXMEMORY_ALLKEYS_LRU)) && value >= 0 && value < OBJ_SHARED_INTEGERS) {/*当内存策略不是lru或没有可使用内存和数字介于 0~OBJ_SHARED_INTEGERS使用共享整数字符串,不改变编码*/ decrRefCount(o); incrRefCount(shared.integers[value]); return shared.integers[value]; } else {//编码转换成OBJ_ENCODING_INT if (o->encoding == OBJ_ENCODING_RAW) sdsfree(o->ptr); o->encoding = OBJ_ENCODING_INT; o->ptr = (void*) value; return o; } } //字符串长度小于OBJ_ENCODING_EMBSTR_SIZE_LIMIT,编码转换成OBJ_ENCODING_EMBSTR if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT,编码转换成) { robj *emb; if (o->encoding == OBJ_ENCODING_EMBSTR) return o; emb = createEmbeddedStringObject(s,sdslen(s)); decrRefCount(o); return emb; } //编码为OBJ_ENCODING_RAW,sds的可用大小大于len/10,释放掉可用空间 if (o->encoding == OBJ_ENCODING_RAW && sdsavail(s) > len/10) { o->ptr = sdsRemoveFreeSpace(o->ptr); } return o;}//将OBJ_ENCODING_INT编码字符串转成OBJ_ENCODING_EMBSTR或者OBJ_ENCODING_RAWrobj *getDecodedObject(robj *o) { robj *dec; if (sdsEncodedObject(o)) { incrRefCount(o); return o; } if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_INT) { char buf[32]; ll2string(buf,32,(long)o->ptr); dec = createStringObject(buf,strlen(buf)); return dec; } else { serverPanic("Unknown encoding type"); }}
0 0
- redis object对象系统的源码分析
- redis源码分析 -- redis对象系统
- Redis源码剖析--对象object
- Redis源码剖析--对象Object
- Redis源码分析(二十八)--- object创建和释放redisObject对象
- 结合redis设计与实现的redis源码学习-8.0-object(对象)
- 结合redis设计与实现的redis源码学习-8.1-object.c(对象实现)
- redis t_hash哈希对象的源码分析
- 【redis源码分析】redis对象和hash表---redisObject+hashType
- java的对象祖先Object的源码
- java API——引用类型对象对Object的继承及源码分析
- 关于Ogre自带输入系统OIS(Object-Oriented Input System)的源码分析
- Object 源码分析
- Object类源码分析
- Object源码分析
- Redis源码分析(二十七)--- rio系统I/O的封装
- Redis缓存Object,List对象
- redis 源码分析之对象机制和多态
- 封装CopyFileEx函数,实现文件复制中的暂停,控速,获取进度
- Sublime配置SASS
- mybatis主键返回
- oracle的sys 用户密码是任意的
- IPERF Test for measuring the throughput/speed of a WLAN client.
- redis object对象系统的源码分析
- Android消息机制Message消息池
- C#使用ListView更新数据出现闪烁解决办法
- perl 批量生成分区表
- MySQL大数据量快速分页实现
- js 加法运算问题
- cvsba编译配置
- android移动支付——微信支付
- hbase RowFilter如何根据rowkey查询以及实例实现代码