redis 的对象类型与编码类型
redis 的对象类型,就是面试中常考的 redis 数据类型有哪些 这个问题所问的准确说法,这个对于我们这些只会面试不会开发的程序员来说,简直再熟悉不过啦,就是字符串、哈希、列表、集合、有序集合,这个在 redis 源码中能找到准确的定义:
redis.c
/* Object types */
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4
好多人对 redis 数据结构的理解可能就止步于此了,但其实这只是 redis 对外暴露的抽象结构,其底层实现要看其编码类型来决定使用该编码类型对应的数据结构。
如果一个对象类型只有一种底层数据结构的实现方式,那么这个编码类型就完全多余了,早期的 redis 的确没有这个概念。但后来为了优化性能,一种对象类型可能对应多种不同的编码实现,于是乎关于 redis 底层数据结构的知识点,就开始复杂起来了。编码类型在 redis 源码中也有准确定义:
redis.c
/* 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 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 */
其实我们不用寻找任何额外的二手资料来解释编码类型的作用,直接看源码中的英文注释即可。
对象编码(编码类型):有些对象类型如字符串、哈希,其内部实现可以有多种方式,一个 redis 对象的 encoding字段可以设置下面几个值来表示这个对象的底层编码类型
同一个对象类型,可以有不同的编码类型作为底层实现。而同一种编码类型,也可以支持上层的多种对象类型。他们的关系如下:
读到这里你一定有至少三个疑问:
- 为什么一种对象类型要对应多种编码类型,是为了解决什问题?
- redis 怎么知道什么时候该用这种编码类型,什么时候该用那种编码类型呢,并且编码类型可以随时改变么?
- 各种编码类型的实现原理是什么?(本章不做重点,会贯穿全文介绍一些基本思想,具体的各种实现会在其他篇章专门讲解)
别急,这一部分只是让你知道,redis 面对使用者暴露的只是一个抽象的数据结构,并不代表其底层的具体实现。接下来带你慢慢深入。
为什么一种对象类型要对应多种编码类型
写 redis 的大牛也是程序员,总不能他给自己增加了代码的复杂性,又对性能提升毫无帮助吧?毕竟 redis 这种中间组件必须以性能来取胜同类产品。没错,就是为了 性能提升。
直观感受编码类型的不同
首先我们来直观感受一下同一对象对应不同编码类型这一场景,这里用到了 object encoding xxx 这个 redis 命令来查看某一个 key 其 value 对象所使用的编码类型
127.0.0.1:6379> set number 100
OK
127.0.0.1:6379> object encoding number
"int"
127.0.0