【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记录的是最近被访问时间等(如下图)

相关推荐
難釋懷1 小时前
优惠卷秒杀集群环境下的并发问题
redis·缓存
青衫码上行2 小时前
NoSql数据库简介 + Redis概述
数据库·redis·nosql
可涵不会debug3 小时前
Redis魔法学院——第四课:哈希(Hash)深度解析:Field-Value 层级结构、原子性操作与内部编码优化
数据库·redis·算法·缓存·哈希算法
fengxin_rou4 小时前
【黑马点评实战篇|第一篇:基于Redis实现登录】
java·开发语言·数据库·redis·缓存
我待_JAVA_如初恋4 小时前
Redis常用的数据类型之String
数据库·redis·缓存
学到头秃的suhian5 小时前
Redis跳表
redis
jiunian_cn6 小时前
【Redis】zset数据类型相关指令
数据库·redis·缓存
jiunian_cn7 小时前
【Redis】set数据类型相关指令
数据库·redis·缓存
曲幽7 小时前
FastAPI生命周期管理实战:从启动到关闭,如何优雅地管好你的“资源家当”
redis·python·fastapi·web·shutdown·startup·lifespan
fengxin_rou7 小时前
Redis 核心数据结构:跳表实现、层高设计解析
数据结构·数据库·redis