Redis中的每个对象都由一个redisObject结构表示
,该结构中和
保存数据有关的3个属性分别是
type属性、
encoding属性和
ptr属性:
typedef struct redisObject { // 类型,':'表示占用的bit数 unsigned type:4; // 编码 unsigned encoding:4; // 对象最后一次被访问的时间 unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */ // 引用计数 int refcount; // 指向实际值的指针 void *ptr; } robj;
raw和embstr的区别?
rmbstr编码是专门用于保存短字符串的一种优化编码方式,它只进行一次内存分配和回收,它的StringObject和SDS紧挨。而raw编码单独分配StringObject和SDS,需要两次内存分配和回收
。
在int和embstr的条件不满足时
,会自动转化为raw编码。此外,对embstr执行任何修改命令时
,程序会将对象编码转换成raw,因为embstr没有任何操作函数,它是只读的
。
命令 | 作用 |
---|---|
SET | 设置值 |
GET | 获取值 |
APPEND | 将给定字符串追加到本字符串末尾 |
INCRBYFLOAT | 将字符串转化为long double然后加上给定的数字 |
INCRBY | 对整数值进行加法计算,只能用于int编码 |
DECRBY | 对整数值进行减法计算,只能用于int编码 |
STRLEN | 返回字符串的长度 |
SETRANGE | 将字符串特定索引上的值设置为给定的字符 |
GETRANGE | 返回字符串指定索引上的字符 |
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
不能同时满足这两个条件的,就需要使用linkelist编码。上面的两个值都是可以通过配置文件修改的。
命令 | 作用 |
---|---|
LPUSH | 插入表头 |
RPUSH | 插入表尾 |
LPOP | 从表头返回并删除 |
RPOP | 从表尾返回并删除 |
LINDEX | 返回指定节点保存的元素 |
LLEN | 返回表的长度 |
LINSERT | 将值插入到指定位置 |
LREM | 删除包含了给定元素的节点 |
LTRIM | 删除表中所有不在指定索引范围内的节点 |
LSET | 将指定索引的值更新为指定的值 |
当哈希对象可以同时满足以下两个条件时,哈希对象使用ziplist编码:
不能满足这两个条件的哈希对象需要使用hashtable编码。上面两个上限值可以通过配置文件修改。
命令 | 作用 |
---|---|
HSET | 插入新的键值对 |
HGET | 查找给定键,并返回它的值 |
HEXISTS | 查找给定元素是否存在 |
HDEL | 删除指定键所在的键值对 |
HLEN | 返回键值对的数目 |
HGETALL | 返回所有的键和值 |
集合对象
集合对象的编码可以是intset或者hashtable。
intset编码使用整数集合作为底层实现,整数集合类似于一个数组,详细见上面介绍。
hashtable编码使用字典作为底层实现。
当下面两个条件都被满足时,使用intset编码,否则,使用hashtable编码
集合对象保存的所有元素都是整数值
集合对象保存的元素数量不超过512
第二个条件的上限可以通过配置文件修改。当两个条件中任一个不满足时,就会自动执行编码转换操作
命令 | 作用 |
---|---|
SADD | 添加新元素 |
SCARD | 返回元素数量 |
SISMEMBER | 判断给定的元素是否在集合中 |
SMEMBERS | 返回所有元素 |
SRANDMEMBER | 随机返回集合中的一个元素 |
SPOP | 从列表中随机删除一个值 |
SREM | 删除所有给定的元素 |
skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表
:
/* * 有序集合 */ typedef struct zset { // 字典,键为成员,值为分值 // 用于支持 O(1) 复杂度的按成员取分值操作 dict *dict; // 跳跃表,按分值排序成员 // 用于支持平均复杂度为 O(log N) 的按分值定位成员操作 // 以及范围操作 zskiplist *zsl; } zset;
正如源码注释所说,之所以同时采用两种数据结构来实现,是为了互相弥补对方的不足。zskiplist是为了弥补哈希表不能进行范围查询的缺点,而哈希表将单个元素的查询操作从zskiplist的O(logN)优化到了哈希表的O(1)。
虽然同时使用了两种结构,但是所有的元素节点都是共用的,即真正的节点只有一份,但是它被两种方式使用了。因此,同时使用两种数据结构,并没有浪费空间,且同时提高了范围查询和单值查询的效率。
有序集合的每个元素成员都是一个字符串对象,而每个元素的分支都是一个double类型的浮点数。
当有序集合对象同时满足以下两个条件时,对象使用ziplist编码:
不能满足任何一个,则使用skiplist编码。以上两个条件的上限值是可以在配置文件里修改的。当两个条件的任何一个不被满足时,程序会自动执行编码转换操作。
命令 | 作用 |
---|---|
ZADD | 插入元素 |
ZCARD | 返回集合元素的数量 |
ZCOUNT | 统计分值在给定范围内的节点的数量 |
ZRANGE | 返回给定索引范围内的所有元素 |
ZREVRANGE | 倒序返回给定范围内的元素 |
ZRANK | 返回元素的集合中的排名 |
ZREVRANK | 返回元素在集合中的倒序排名 |
ZREM | 删除所有包含了给定成员的跳跃表节点 |
ZSCORE | 返回给定元素的分值 |