【Redis】深入理解 Redis 常用数据类型源码及底层实现(2.版本区别+dictEntry & redisObject详解)

【Redis】深入理解 Redis 常用数据类型源码及底层实现(1.结构与源码概述)一文中我们了解到Redis有如下8种底层数据结构:

  • SDS动态字符串
  • 双向链表
  • 压缩列表 ziplist
  • 哈希表 hashtable
  • 跳表 skiplist
  • 整数集合 intset
  • 快速列表 quicklist
  • 紧凑列表 listpack

关于这些底层数据结构是如何构成我们熟悉的Set、Sorted Set 、List、Hash......的Redis和7并不完全一致,我们来看看两个版本之间的区别

Redis 6.0.5

  • String -> 动态字符串
  • Set -> 哈希表+整数数组
  • Sorted Set -> 跳表+压缩列表zipList
  • List -> 双端链表+压缩列表zipList
  • Hash -> 哈希表+压缩列表zipList

Redis 7 以后

2021.11.29以后,Redis 7 以后,没有ziplist了(ziplist被listpack取代)

  • Hash -> 哈希表+紧凑列表listpack
  • List -> quiecklist
  • Sorted Set -> 跳表+紧凑列表listpack
  • Set -> 哈希表+整数数组
  • String -> 动态字符串

redisObject操作的底层定义位于server.h文件(Redis启动时就会加载server.),如下图

每个键值对都会有一个dictEntry

set hello world为例,因为Redis是KV键值对的数据库,每个键值对都会有一个dictEntrydictEntry表示哈希表节点的结构,指针*key(下图红

色框框部分)、指针*value(下图黄色框框部分),指针*next指向下一个dictEntrydictEntry对象的声明在dict.c文件中,如下图:

其中*key指向String对象,*value既能指向String对象也能指向其他集合对象(如ListSetZSetHash),键值对的时间复杂度是O(1),值得注意的是,这里指向的都是Redis内部的抽象对象(redisObject

redisObject结构的作用

Redis定义了redisObject结构体来表示string、hash、list、set、zset等数据类型,即Redis每个对象都是一个redisObject结构**

redisObject对象的声明位于server.h文件内,如下图:

c 复制代码
struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;
};

为了便于操作,Redis采用了redisObject结构来统一5种不同的数据类型(下图绿色部分),这样所有的数据类型就可以以相同的形式在函数间传递而不用使用特定的类型结构。同时,为了识别不同的数据类型,redisObject中定义了typeencoding两个字段对不同的数据类型加以区别。

简单理解,redisObject就是stringhashlistsetzset的父类,可以在函数间传递时隐藏具体的类型信息。

我们依次解释下redisObject中的各个参数:

  • type:对象的类型,4位(5种)

    • OBJ_STRINGOBJ_LISTOBJ_HASHOBJ_SETOBJ_ZSET
    • 使用type xxx命令进行查看
  • encoding:当前值对象底层存储的编码类型,4位,即表示该类型的物理编码方式(同一种数据类型可能有不同的编码方式,比如String就提供了0、1、8这三种编码方式)

    • 使用object encoding xxx命令进行查看
  • lru:清除算法,lru表示当内存超限时采用LRU算法清除内存中的对象(24位,如果是LRU则记录对象最后一次被程序访问的时间(与内存回收相关)?

  • refcount:引用计数,当refcount为0时,表示该对象已经不被任何对象引用(可以被当作垃圾回收了)

  • *ptr:指向真正的底层数据结构的指针

    • *ptr指向的底层数据结构有:SDS、双向链表、压缩列表、哈希表、跳表、整数集合等(指向下图中的黄色部分的箭头)

我们来举个例子,对于一条指令set age 17,当执行这条指令时,底层机会生成一个redisObject对象,这个对象中的typeStringencodingintlru记录的是最近被访问时间等(如下图)

相关推荐
星星点点洲17 分钟前
【Redis】谈谈Redis的设计
数据库·redis·缓存
Lion Long5 小时前
CodeBuddy 中国版 Cursor 实战:Redis+MySQL双引擎驱动〈王者荣耀〉战区排行榜
数据库·redis·mysql·缓存·腾讯云·codebuddy首席试玩官·codebuddy
柯南二号12 小时前
MacOS 用brew 安装、配置、启动Redis
redis
星星点点洲15 小时前
【Redis】RedLock实现原理
redis·缓存
我来整一篇15 小时前
用Redis的List实现消息队列
数据库·redis·list
加什么瓦15 小时前
Redis——数据结构
数据库·redis·缓存
lybugproducer16 小时前
浅谈 Redis 数据类型
java·数据库·redis·后端·链表·缓存
青山是哪个青山16 小时前
Redis 常见数据类型
数据库·redis·bootstrap
杨不易呀17 小时前
Java面试全记录:Spring Cloud+Kafka+Redis实战解析
redis·spring cloud·微服务·kafka·高并发·java面试·面试技巧