标签:3.0 空间 bst 存储 some 编码方式 lis 种类型 底层实现
Redis使用 string list zset hash set 五大数据类型来存储键和值。在每次生成一个键值对时,都会生成两个对象,一个储存键一个储存值。redis定义了RealObject结构体表示他们
typedef struct redisObject { unsigned type:4; unsigned encoding:4; unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */ int refcount; void *ptr; } robj;
1.type
redis 的对象有五种类型,分别是string list zset hash set,type就是用来标识这五种类型的。
/* Object types */ #define OBJ_STRING 0 #define OBJ_LIST 1 #define OBJ_SET 2 #define OBJ_ZSET 3 #define OBJ_HASH 4
(在redis中,键总是一个字符串对象,而值可以是字符串、列表、集合等对象)
2.编码类型encoding
redis的对象的实际编码方式由encoding参数指定,也就是ptr指针指向的数据以何种底层实现存放。
/* Objects encoding. Some kind of objects like Strings and Hashes can be * internally represented in multiple ways. The ‘encoding‘ field of the object * is set to one of this fields for this object. */ #define OBJ_ENCODING_RAW 0 /* Raw representation -- 简单动态字符串sds*/ #define OBJ_ENCODING_INT 1 /* Encoded as integer -- long类型的整数*/ #define OBJ_ENCODING_HT 2 /* Encoded as hash table -- 字典dict*/ #define OBJ_ENCODING_ZIPMAP 3 /* Encoded as zipmap -- 3.2.5版本后不再使用 */ #define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list -- 双向链表*/ #define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist -- 压缩列表*/ #define OBJ_ENCODING_INTSET 6 /* Encoded as intset -- 整数集合*/ #define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist -- 跳表*/ #define OBJ_ENCODING_EMBSTR 8 /* Embedded sds string encoding -- embstr编码的sds*/ #define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists -- 由双端链表和压缩列表构成的高速列表*/
可以通过 object encoding key 指令查看值对象的编码
3.访问时间lru
表示该对象最后一次呗访问的时间,占用24bit。保存该值的目的是为了计算对象的空转时长,便于决定是否应该释放该键。
4.引用计数refcount
c语言不具备自动内存回手机制,所以为每个对象设定了引用计数。
void decrRefCount(robj *o) { // 引用计数为小于等于0,报错 if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0"); // 引用计数等于1,减1后为0 // 须要释放整个redis对象 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; } // 释放redis对象 zfree(o); } else { // 引用计数减1 o->refcount--; } }
5.ptr指向实际存放的对象
RAW编码方式使用简单动态字符串sds来保存字符串对象
struct sdshdr { unsigned int len; //buf中已经占用的空间的长度 unsigned int free;//buf中剩余的可用空间长度 char buf[];//数据存放位置 };
从Redis 3.0 版本开始,字符串引入了embstr编码方式,长度小于OBJ_ENCONDING_EMBSTR_SIZE_LIMIT的字符串将以EMBSTR方式存储。
EMBSTR方式的意思是 embedded string,字符串的空间将会和redisObject对象的空间一起分配,两者分配在同一个内存块中。
redis中内存分配使用的是jemalloc,jemalloc分配内存的时候是按照8,16,32,64作为块的单位进行飞扑的。为了保证采用这种编码方式的字符串能被jemalloc分配在同一个块(chunk)中,该块长度不能超过64,故字符串长度限制OBJ_ENCONDING_EMBSTR_SIZE_LIMIT = 64 - sizeof(‘\0‘) -sizeof(robj) -sizeof(sdshdr) =39.
这样可以有效减少内存分配的次数,提高内存分配的效率,降低碎片率。
结构同样适用 sdshdr(见上文)
标签:3.0 空间 bst 存储 some 编码方式 lis 种类型 底层实现
原文地址:https://www.cnblogs.com/chafanbusi/p/10711819.html