面试官问我 Redis 数据类型,我回答了 8 种.


面试官问我 Redis 数据类型,我回答了 8 种.

文章插图
 
面试官:小明呀,redis 有几种数据结构呀?
小明:8 种
面试官:那你说一下分别是什么?
小明:raw,int,ht,zipmap,linkedlist,ziplist,intset,skiplist,embstr
面试官:额,你在说什么?
小明:在回答你的问题呀,这个问题我可是有过研究的,不会错的
面试官:好吧,今天的面试先到这里,你回去等通知吧
小明:...
上面发生的对话,到底是面试官有问题,还是小明有问题呢?其实是都有问题的,面试官的提问不准确,小明的回答也不准确 。
但可以看出,面试官的水平一般,因为听到这些名词并不知道小明说的是 redis 底层的编码类型,进而错失了深入挖掘小明技术潜力的机会 。而小明也有些自作聪明,忽略了面试官想考察的知识点,把自己最近看的一些皮毛拿出来秀了秀,结果导致了一场误会 。
就着上面这个引子,我们本篇文章就来聊聊,redis 中的数据结构那些事 。
redis 源码选取的版本: 3.0.0
本篇文章的目标:知道 redis 的编码类型这个概念,并按照源码级的深度去理解为什么要设置不同的编码类型,但不会过多展开各种底层数据结构的细节
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 数据类型,我回答了 8 种.

文章插图
 
读到这里你一定有至少三个疑问:
  • 为什么一种对象类型要对应多种编码类型,是为了解决什问题?
  • redis 怎么知道什么时候该用这种编码类型,什么时候该用那种编码类型呢,并且编码类型可以随时改变么?
  • 各种编码类型的实现原理是什么?(本章不做重点,会贯穿全文介绍一些基本思想,具体的各种实现会在其他篇章专门讲解)
别急,这一部分只是让你知道,redis 面对使用者暴露的只是一个抽象的数据结构,并不代表其底层的具体实现 。接下来带你慢慢深入 。
为什么一种对象类型要对应多种编码类型写 redis 的大牛也是程序员,总不能他给自己增加了代码的复杂性,又对性能提升毫无帮助吧?毕竟 redis 这种中间组件必须以性能来取胜同类产品 。没错,就是为了 性能提升 。
直观感受编码类型的不同首先我们来直观感受一下同一对象对应不同编码类型这一场景,这里用到了 object encoding xxx 这个 redis 命令来查看某一个 key 其 value 对象所使用的编码类型


推荐阅读