redis中把所有用到的数据结构都抽象成对象,所以对象就是对SDS,压缩列表,双向链表和字典的集合,可以分为字符串对象,列表对象,哈希对象,集合对象,有序集合对象。
对象的结构体
typedef struct redisObject {
/*
REDIS_STRING 字符串对象
REDIS_LIST 列表对象
REDIS_HASH 哈希对象
REDIS_SET 集合对象
REDIS_ZSET 有序集合对象
*/
unsigned type:4;
// 编码方式,相同的类型可以不同的编码方式以节省内存
unsigned encoding:4;
// 对象最后一次被访问的时间 // 该属性记录了对象最后一次被命令程序访问的时间: 10s统计一次
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
// 用于共享对象的引用次数,用于管理对象生命,引用次数为0时,表示可以释放该对象(不是必须要释放)
int refcount;
void *ptr; // 对象的指针,如果是整数的字符串对象,直接为整数值
} robj;
字符串对象 | REDIS_STRING | REDIS_ENCODING_INT | LONG范围内整数 |
REDIS_ENCODING_EMBSTR | 字符串的长度小于等于REDIS_ENCODING_EMBSTR_SIZE_LIMIT,内存连续,防止内存蛀虫,只需要申请一次内存,速度快 | ||
REDIS_ENCODING_RAW | 字符串的长度大于REDIS_ENCODING_EMBSTR_SIZE_LIMIT,适用于长字符串 | ||
列表对象 | REDIS_LIST | REDIS_ENCODING_ZIPLIST | 节省空间 |
REDIS_ENCODING_LINKEDLIST | 适合数据量大 | ||
哈希对象 | REDIS_HASH | REDIS_ENCODING_ZIPLIST | 节省空间 |
REDIS_ENCODING_HT | 适合数据量大 | ||
集合对象 | REDIS_SET | REDIS_ENCODING_INTSET | 节省空间 |
REDIS_ENCODING_HT | 适合数据量大。底层字典中的键的对象,值指针为空。 | ||
有序集合 | REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 节省空间 |
REDIS_ENCODING_SKIPLIST | 底层同时使用字典和跳跃表保存,结构体为zset(redis-3.0\src\redis.h),好处是可以使用上可以综合两种数据结构的优点,比如字典对取值是O(1),跳跃表可以支持范围操作更快。两种数据结构都指向相同的数据对象,所以内存没有浪费。 |
共享对象
为了节约内存,redis规定当创建对象的值为正整数且小于OBJ_SHARED_INTEGERS时,其对象为共享对象,以后需要再次新增该对象时,不需要额外申请内存,只需要refcount+1即可。
只要整数型字符串对象才可以作为共享对象,因为直接将值保存在内存中,匹配的快,否则匹配太慢。