美文网首页
Redis 详解之Redis 的 9 种数据结构图解

Redis 详解之Redis 的 9 种数据结构图解

作者: you的日常 | 来源:发表于2021-12-23 11:06 被阅读0次

    Redis 为什么那么快?

    除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效的处理。

    因此,这次我们就来好好聊一下 Redis 数据结构,这个在面试中太常问了。

    注意,Redis 数据结构并不是指 String(字符串)对象、List(列表)对象、Hash(哈希)对象、Set(集合)对象和 Zset(有序集合)对象,因为这些是 Redis 键值对中值的数据类型,也就是数据的保存形式,这些对象的底层实现的方式就用到了数据结构

    我画了一张 Redis 数据类型(也叫 Redis 对象)和底层数据结构的对应关图,左边是 Redis 3.0版本的,也就是《Redis 设计与实现》这本书讲解的版本,现在看还是有点过时了,右边是现在 Github 最新的 Redis 代码的(还未发布正式版本)。

    image

    可以看到,Redis 数据类型的底层数据结构随着版本的更新也有所不同,比如:

    • 在 Redis 3.0 版本中 List 对象的底层数据结构由「双向链表」或「压缩表列表」实现,但是在 3.2 版本之后,List 数据类型底层数据结构是由 quicklist 实现的;
    • 在最新的 Redis 代码(还未发布正式版本)中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

    本文把新旧版本的数据结构说图解一遍,共有 9 种数据结构:SDS、双向链表、压缩列表、哈希表、跳表、整数集合、quicklist、listpack。

    image

    键值对数据库是怎么实现的?

    在开始讲数据结构之前,先给介绍下 Redis 是怎样实现键值对(key-value)数据库的。

    Redis 的键值对中的 key 就是字符串对象,而 value 可以是字符串对象,也可以是集合数据类型的对象,比如 List 对象、Hash 对象、Set 对象和 Zset 对象。

    举个例子,我这里列出几种 Redis 新增键值对的命令:

    > SET name "xiaolincoding"
    OK
    
    > HSET person name "xiaolincoding" age 18
    0
    
    > RPUSH stu "xiaolin" "xiaomei"
    (integer) 4
    

    这些命令代表着:

    • 第一条命令:name 是一个字符串键,因为键的值是一个字符串对象
    • 第二条命令:person 是一个哈希表键,因为键的值是一个包含两个键值对的哈希表对象
    • 第三条命令:stu 是一个列表键,因为键的值是一个包含两个元素的列表对象

    这些键值对是如何保存在 Redis 中的呢?

    Redis 是使用了一个「哈希表」保存所有键值对,哈希表的最大好处就是让我们可以用 O(1) 的时间复杂度来快速查找到键值对。哈希表其实就是一个数组,数组中的元素叫做哈希桶。

    Redis 的哈希桶是怎么保存键值对数据的呢?

    哈希桶存放的是指向键值对数据的指针(dictEntry*),这样通过指针就能找到键值对数据,然后因为键值对的值可以保存字符串对象和集合数据类型的对象,所以键值对的数据结构中并不是直接保存值本身,而是保存了 void * key 和 void * value 指针,分别指向了实际的键对象和值对象,这样一来,即使值是集合数据,也可以通过 void * value 指针找到。

    我这里画了一张 Redis 保存键值对所涉及到的数据结构。

    image

    这些数据结构的内部细节,我先不展开讲,后面在讲哈希表数据结构的时候,在详细的说说,因为用到的数据结构是一样的。这里先大概说下图中涉及到的数据结构的名字和用途:

    • redisDb 结构,表示 Redis 数据库的结构,结构体里存放了指向了 dict 结构的指针;
    • dict 结构,结构体里存放了 2 个哈希表,正常情况下都是用「哈希表1」,「哈希表2」只有在 rehash 的时候才用,具体什么是 rehash,我在本文的哈希表数据结构会讲;
    • ditctht 结构,表示哈希表的结构,结构里存放了哈希表数组,数组中的每个元素都是指向一个哈希表节点结构(dictEntry)的指针;
    • dictEntry 结构,表示哈希表节点的结构,结构里存放了 **void * key 和 void * value 指针, key 指向的是 String 对象,而 value 则可以指向 String 对象,也可以指向集合类型的对象,比如 List 对象、Hash 对象、Set 对象和 Zset 对象。

    特别说明下,void * key 和 void * value 指针指向的是 Redis 对象,Redis 中的每个对象都由 redisObject 结构表示,如下图:

    image

    对象结构里包含的成员变量:

    相关文章

      网友评论

          本文标题:Redis 详解之Redis 的 9 种数据结构图解

          本文链接:https://www.haomeiwen.com/subject/utjhqrtx.html