对于Redis来说,其实我们操作的数据类型就是String,List、Set、Zset、Hash,但是具体低层使用什么编码进行存储,在面试中是一个高频面试题,所以今天大概整理下对应的。
RedisObject与DictEntry
其实对于key来说一般都是String类型的字符串对象,value则为Redis对象。
Redis底层其实定义了RedisObject结构体,以及表示Redis的数据节点:dictEntry
一个案例
比如我们设置一个 set hello world ,
SET hello world
"OK"TYPE hello # 查看类型
"string"OBJECT encoding hello # 查看编码
"embstr"
字符串
对于字符串来说,其实主要的物理编码就是int、embstr、raw。如果是整数就使用int。embstr保存长度小于44字节的字符串。raw保存长度大于44字节的字符串。
其实Redis本身使用C语言进行编写,但是没有使用C语言的字符串,或者说字符数组进行表示。而是自己二次开发构建了一个属于自己的结构 SDS。Redis多有键值对包含的字符串对象都是SDS实现的。
为什么需要重写设计一个SDS
Hash数据结构
hash-max-ziplist-entries:使用压缩列表保存时哈希集合中的最大元素个数。
hash-max-ziplist-value:使用压缩列表保存时哈希集合中单个元素的最大长度。
当键的个数不超过entries的个数以及字段名不超过value长度,使用ziplist,否则就是hashtable
CONFIG get hash*
1) "hash-max-ziplist-entries"
2) 512
3) "hash-max-ziplist-value"
4) 64HSET user name z3
0OBJECT encoding user
"ziplist"
List数据结构
config get list*1) "list-max-ziplist-size"
2) -2
3) "list-compress-depth"
4) 0
(1) ziplist压缩配置:list-compress-depth 0
表示一个quicklist两端不被压缩的节点个数。这里的节点是指quicklist双向链表的节点,而不是指ziplist里面的数据项个数
0: 是个特殊值,表示都不压缩。这是Redis的默认值。
(2) ziplist中entry配置:list-max-ziplist-size -2
当取正值的时候,表示按照数据项个数来限定每个quicklist节点上的ziplist长度。比如,当这个参数配置成5的时候,表示每个quicklist节点的ziplist最多包含5个数据项。当取负值的时候,表示按照占用字节数来限定每个quicklist节点上的ziplist长度。这时,它只能取-1到-5这五个值.
-2: 每个quicklist节点上的ziplist大小不能超过8 Kb。(-2是Redis给出的默认值)
总结
1.字符串
int:8个字节的长整型。
embstr:小于等于44个字节的字符串。
raw:大于44个字节的字符串。
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
2. 哈希
ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64 字节)时,
Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的 结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。
hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使 用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。
3. 列表
ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置 (默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时 (默认64字节),
Redis会选用ziplist来作为列表的内部实现来减少内存的使 用。
linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用 linkedlist作为列表的内部实现。quicklist ziplist和linkedlist的结合以ziplist为节点的链表(linkedlist)
4. 集合
intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会用intset来作为集合的内部实现,从而减少内存的使用。
hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。
5. 有序集合
ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist- entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配 置(默认64字节)时,
Redis会用ziplist来作为有序集合的内部实现,ziplist 可以有效减少内存的使用。
skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作 为内部实现,因为此时ziplist的读写效率会下降。