Redis使用对象来表示数据库中的键和值,每次当我们在Redis数据库中新创建一个键值对时,我们会至少会创建两个对象,一个是键对象,另一个是值对象。
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 对象最后一次被访问的时间
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
// 引用计数
int refcount;
// 指向实际值的指针
void *ptr;
} robj;
Redis的对象类型共有五种
/* Object types */
// 对象类型
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4
对象由什么样的数据结构存储,取决于encoding的值,ptr指向实际的数据结构
// 对象编码
#define REDIS_ENCODING_RAW 0 /* Raw representation */
#define REDIS_ENCODING_INT 1 /* Encoded as integer */
#define REDIS_ENCODING_HT 2 /* Encoded as hash table */
#define REDIS_ENCODING_ZIPMAP 3 /* Encoded as zipmap */
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_INTSET 6 /* Encoded as intset */
#define REDIS_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
#define REDIS_ENCODING_EMBSTR 8 /* Embedded sds string encoding */
字符串对象
1. 字符串对象的编码可以是int,raw,embstr
比如
SET number 10086
那么字符串就是用int编码,对应的底层数据结构为long
2. 如果string的长度大于39,那么就用编码为RAW,底层数据结构是SDS
3. 如果string的长度小于39,那么就会用EMBSTR编码, 底层数据结构也是SDS
这些编码方式可以互相转换。
列表对象
1. 列表对象可以用ziplist或者linkedlist编码,底层分别是压缩列表和双向链表。
哈希对象
ziplist和hashtable
集合对象
intset和hashtable
有序集合
ziplist和skiplist
对象通过引用技数实现内存回收。
重点总结:
1. Redis数据库中的每个key和value都是一个对象
2. Redis有String, Hash, List, Set, ZSet五种类型的对象,每种对象有两种以上的编码方式,可以在不同场景下优化。
3. 服务器在执行命令时,会先检查对象类型
4. Redis对象内存管理采用引用计数
5. Redis会共享0到9999的字符串对象
5. 对象会记录最后一次访问时间,用于LRU。