这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
Redis的背景我们就不需要过多的进行介绍了,下面直入主题
Redis常用的5种数据类型:
String,List,Hash,Set,ZSet
下面我们直接给出结论 5种数据类型对应的地层结构为:
1.String
- int(整数型)
- raw(简单动态字符串SDS)
- embstr(embstr编码的简单动态字符串)
2.List
ziplist(压缩列表) linkedlist(双端链表)
3.Hash
ziplist(压缩列表) hashtable(哈希表,字典)
4.Set
iniset(整数集合) hashtable(哈希表,字典)
5.ZSet
ziplist(压缩列表) skiplist(跳表)
redisObject
以上结构大家都很熟悉了,这次我们来说说Redis的对象:redisObject(robj)
Redis使用这么多种数据结构,那么Redis是如何管理和使用这些数据结构的呢,就是通过redisObject,首先我们来看下它的定义
redisObject的定义
typedef struct redisObject{
unsigned type:4; //类型
unsigned encoding:4; //编码
void *ptr; //指向底层数据结构的指针
int refcount; //引用计数
unsigned lru:22; //记录最后一次被程序访问的时间
}robj
type属性记录了对象的类型,他对应的取值就是redis的5种数据类型
/* Object types */
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4
encoding属性记录了编码方式,也就是对应了实际的底层数据结构
/* 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 */
#define OBJ_ENCODING_INT 1 /* Encoded as integer */
#define OBJ_ENCODING_HT 2 /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3 /* Encoded as zipmap */
#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 */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */
ptr则是指向真正数据的数据指针。如一个string类型,ptr可能指向一个sds,如一个hash类型,ptr则可能指向一个ziplist或是一个hashtable
refcount属性是该对象被应用的次数,被引用一次,数值+1,当引用技术为0时,则会被释放 我们来看下相应的代码
void incrRefCount(robj *o) {
o->refcount++;
}
void decrRefCount(robj *o) {
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
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 {
o->refcount--;
}
}
lru熟悉用来标记对象的空转时长,如果服务器打开了maxmemory的选项,如果服务器超出了内存上线,会根据这个属性进行内存释放
多态
有了redisObject之后, 在执行处理数据类型的命令时, 进行类型检查和对编码进行多态操作就简单得多了.
如针对一个hash类型执行hset操作,那么执行流程如下:
以上我们大概了解了Redis组织对象的方式:redisObject redisObject管理着Redis底层的多种数据结构