对象
上面我们介绍了Redis主要用到的数据结构,基于这些数据结构Redis创建了一个对象系统,包含了**字符串对象**、**列表对象**、**hash对象**、**集合对象**和**有序集合对象**等五种类型的对象。
通过这五种不同类型的对象,Redis可以在执行命令之前,根据对象的类型拉覅判断一个对象是否可以执行给定的命令。使用对象的另一个好处是,我们可以针对不同的使用场景,为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。
除此之外,Redis的对象系统还实现了基于引用计数技术的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会被自动释放;另外,Redis还通过引用计数实现了对象共享机制,这一机制可以在适当条件下,通过让多个数据库键共享同意给对象来节约内存。
最后,Redis的对象带有访问时间记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的那些键可能会优先被服务器删除。
对象的基础类型
Redis中的每个对象都由一个redisObjects结构表示。
// server.h
// 对象类型
/* The actual Redis Object */
#define OBJ_STRING 0 /* String object. */
#define OBJ_LIST 1 /* List object. */
#define OBJ_SET 2 /* Set object. */
#define OBJ_ZSET 3 /* Sorted set object. */
#define OBJ_HASH 4 /* Hash object. */
/* The "module" object type is a special one that signals that the object
* is one directly managed by a Redis module. In this case the value points
* to a moduleValue struct, which contains the object value (which is only
* handled by the module itself) and the RedisModuleType struct which lists
* function pointers in order to serialize, deserialize, AOF-rewrite and
* free the object.
*
* Inside the RDB file, module types are encoded as OBJ_MODULE followed
* by a 64 bit module type ID, which has a 54 bits module-specific signature
* in order to dispatch the loading to the right module, plus a 10 bits
* encoding version. */
#define OBJ_MODULE 5 /* Module object. */
#define OBJ_STREAM 6 /* Stream object. */
// 对象编码类型
/* 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 /* No longer used: old list encoding. */
#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 */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */
#define LRU_BITS 24
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
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). */
int refcount;
void *ptr;
} robj;
可以使用type命令来获取键值对中值的对象类型
127.0.0.1:6379> set mgs "hello world"
OK
127.0.0.1:6379> type msg
string
127.0.0.1:6379> rpush numbers 1 3 5
(integer) 6
127.0.0.1:6379> type numbers
list
127.0.0.1:6379> hmset profile name Tom age 25 career Programmer
OK
127.0.0.1:6379> type profile
hash
127.0.0.1:6379> sadd fruits apple banana cherry
(integer) 3
127.0.0.1:6379> type fruits
set
127.0.0.1:6379> zadd price 8.5 apple 5.2 banana 6.0 cherry
(integer) 3
127.0.0.1:6379> type price
zset
基本对象的结构图
基本对象.PNG对象的类型和编码
类型和编码的对应关系:
类型 | 编码 | 对象 |
---|---|---|
OBJ_STRING | OBJ_ENCODING_INT | 使用整数值实现的字符串对象 |
OBJ_STRING | OBJ_ENCODING_EMBSTR | 使用embstr编码的sds字符串实现的字符串对象 |
OBJ_STRING | OBJ_ENCODING_RAW | 使用原始的sds字符串实现的字符串对象 |
OBJ_LIST | OBJ_ENCODING_ZIPLIST | 使用压缩列表实现的列表对象 |
OBJ_LIST | OBJ_ENCODING_LINKEDLIST | 使用双向链表实现的列表对象(已废弃) |
OBJ_LIST | OBJ_ENCODING_QUICKLIST | Redis中的列表对象在版本3.2之前,列表底层的编码是ziplist和linkedlist实现的,但是在版本3.2之后,重新引入了一个 quicklist 的数据结构,列表的底层都由quicklist实现 |
OBJ_HASH | OBJ_ENCODING_ZIPLIST | 使用压缩列表实现的hash对象 |
OBJ_HASH | OBJ_ENCODING_HT | 使用字典实现的hash对象 |
OBJ_SET | OBJ_ENCODING_INTSET | 使用整数集合实现的集合对象 |
OBJ_SET | OBJ_ENCODING_HT | 使用字典实现的集合对象 |
OBJ_ZSET | OBJ_ENCODING_ZIPLIST | 使用压缩列表实现的有序集合对象 |
OBJ_ZSET | OBJ_ENCODING_SKIPLIST | 使用跳跃表和字典实现的有序集合对象 |
可以使用object encoding命令获取对象类型
127.0.0.1:6379> set msgs "good night"
OK
127.0.0.1:6379> object encoding msgs
"embstr"
网友评论