第八章 对象
Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象,每种对象都用到了至少一种我们前面锁介绍的数据结构。
8.1 对象的类型与编码
Redis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(键对象)。
Redis中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type属性,encodeing属性和ptr属性:
typedef struct redisObject{
//类型
unsigned type:4;
//编码
unsigned encoding:4;
//指向底层实现数据结构的指针
void *ptr;
}robj;
8.1.1 类型
对象的type属性记录了对象的类型:
类型常量 | 对象的名称 |
---|---|
Redis_string | 字符串对象 |
redis_list | 列表对象 |
redis_hash | 哈希对象 |
redis_set | 集合对象 |
redis_zset | 有序集合对象 |
8.1.1 编码和底层实现
encoding属性记录了对象所使用的编码,如下所示:
编码常量 | 编码锁对应的底层数据结构 |
---|---|
redis_encoding_int | long类型的整数 |
redis_encoding_menbstr | embstr编码的简单动态字符串 |
redis_encoding_raw | 简单动态字符串 |
redis_encoding_ht | 字典 |
redis_encoding_linkedlist | 双端链表 |
redis_encoding_ziplist | 压缩列表 |
redis_encoding_intset | 整数集合 |
redis_encoding_skiplist | 跳跃表和字典 |
通过encoding属性来设定对象所使用的编码,而不是为特 定类型的对象关联一种固定的编码,极大地提升了redis的灵活性和效率。
8.2 字符串对象
字符串对象的编码可以是int、raw或者embstr
字符串命令的实现:68页
8.3 列表对象
列表对象可以是ziplist或者linkedlist
列表命令的实现:71页
8.4 哈希对象
哈希对象的编程可以是ziplist或者hashtable
哈希命令的实现:74页
8.5 集合对象
集合对象的编码可以是intset或者hashtable
集合命令的实现:76~77页
8.6 有序集合对象
有序集合的编码可以是ziplist或者skiplist
有序集合命令的实现结构:81页
8.7 类型检查与命令多态
Redis中用于操作键的命令基本上可以分为两种类型: 其中一种命令可以对任何类型的键执行,比如说DEL命令、EXPIRE命令、RENAME命令、TYPE命令、OBJECT命令等。
而另一种命令只能对特定类型的键执行,比如说:
- SET、GET、APPEND、STRLEN —— 字符串
- HDEL、HSET、HGET、HLEN —— 哈希键
- HPUSH、LPOP、LINSERT、LINE —— 列表键
- SADD、SPOP、SINTER、SCARD —— 集合键
- ZADD、ZCARD、ZRANK、ZSCORE —— 有序集合键
8.7.1 类型检查的实现
类型特定命令所进行的类型检查是通过redisObject结构的type属性来实现的。
8.7.2 多态命令的实现
根据值对象的编码方式,选择正确的命令实现代码来执行命令。
8.8 内存回收
redis在自己的对象系统中构建了一个用计数技术实现的内存回收机制,通过这一种机制,程序可以通过跟踪对象的引用计数信息,在适当的时候自动释放对象并进行内存回收。
8.9 对象共享
除了用于实现引用计数内存回收机制之外,对象的引用计数属性还带有对象共享的作用。
8.10 对象的空转时长
redisObject结构包含的最后一个属性lru属性,该属性记录了对象最后一次呗命令程序访问的时间。
Object idletime命令可以打印出给定键的空转时长,这一空转时长就是通过将当前时间减去键的值对象的lru时间计算的出来的。