前言:
Redis也有自己的数据类型,包含string,list,hash,set,sorted set。下面就对每种数据类型原理以及操作做一个详细的介绍。
Redis是面向编程的语言,除了字符串,其他类型怎么表示呢?
Redis中定义了一个对象的结构体:
/* * Redis 对象 */ typedef struct redisObject { // 类型 unsigned type:4; // 不使用(对齐位) unsigned notused:2; // 编码方式 unsigned encoding:4; // LRU 时间(相对于 server.lruclock) unsigned lru:22; // 引用计数 int refcount; // 指向对象的值 void *ptr; } robj;
type表示了该对象的对象类型,即上面五个中的一个。但为了提高存储效率与程序执行效率,每种对象的底层数据结构实现都可能不止一种。encoding就表示了对象底层所使用的编码。下面先介绍每种底层数据结构的实现,再介绍每种对象类型都用了什么底层结构并分析他们之间的关系。
Redis对象底层数据结构共八种:
编码常量 编码所对应的底层数据结构
REDIS_ENCODING_INT(long 类型的整数)
REDIS_ENCODING_EMBSTR embstr (编码的简单动态字符串)
REDIS_ENCODING_RAW (简单动态字符串)
REDIS_ENCODING_HT (字典)
REDIS_ENCODING_LINKEDLIST (双端链表)
REDIS_ENCODING_ZIPLIST (压缩列表)
REDIS_ENCODING_INTSET (整数集合)
REDIS_ENCODING_SKIPLIST (跳跃表和字典)
string
Redis的字符串也是字符序列,一个Key对应一个Value,它是Redis里面最为基础的数据存储类型。字符串类型是二进制安全(字符串不是根据某种特殊的标志来解析的,无论输入是什么,总能保证输出是处理的原始输入而不是根据某种特殊格式来处理)的,可以包含任何数据等等。
一:实现原理:
在C语言中,字符串可以用' '结尾的char数组标示。这种简单的字符串表示,在大多数情况下都能满足要求,但是不能高效的计算length和append数据。所以Redis自己实现了SDS(简单动态字符串)的抽象类型。
字符串的编码可以是int,raw或者embstr。如果一个字符串内容可转为long,那么该字符串会被转化为long类型,对象ptr指向该long,并且对象类型也用int类型表示。普通的字符串有两种,embstr和raw。如果字符串对象的长度小于44字节,就用embstr对象。否则用的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; } /* Create a string object with encoding OBJ_ENCODING_RAW, that is a plain * string object where o->ptr points to a proper sds string. */ robj *createRawStringObject(const char *ptr, size_t len) { return createObject(OBJ_STRING,sdsnewlen(ptr,len)); } /* Create a string object with encoding OBJ_ENCODING_EMBSTR, that is * an object where the sds string is actually an unmodifiable string * allocated in the same chunk as the object itself. */ robj *createEmbeddedStringObject(const char *ptr, size_t len) { robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1); struct sdshdr8 *sh = (void*)(o+1); o->type = OBJ_STRING; o->encoding = OBJ_ENCODING_EMBSTR; o->ptr = sh+1; o->refcount = 1; o->lru = LRU_CLOCK(); sh->len = len; sh->alloc = len; sh->flags = SDS_TYPE_8; if (ptr) { memcpy(sh->buf,ptr,len); sh->buf[len] = '