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

相关推荐
indexsunny8 小时前
互联网大厂Java面试实战:Spring Boot微服务在电商场景中的应用与挑战
java·spring boot·redis·微服务·kafka·spring security·电商
摇滚侠13 小时前
阿里云安装的 Redis 在什么位置,如何找到 Redis 的安装位置
redis·阿里云·云计算
啦啦啦_999914 小时前
Redis-2-queryFormat()方法
数据库·redis·缓存
forestsea16 小时前
深入理解Redisson RLocalCachedMap:本地缓存过期策略全解析
redis·缓存·redisson
佛祖让我来巡山17 小时前
Redis 为什么这么快?——「极速快递站」的故事
redis·redis为什么快?
啦啦啦_999918 小时前
Redis-0-业务逻辑
数据库·redis·缓存
自不量力的A同学19 小时前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
fengxin_rou19 小时前
[Redis从零到精通|第四篇]:缓存穿透、雪崩、击穿
java·redis·缓存·mybatis·idea·多线程
是阿楷啊20 小时前
Java大厂面试场景:音视频场景中的Spring Boot与微服务实战
spring boot·redis·spring cloud·微服务·grafana·prometheus·java面试
笨蛋不要掉眼泪20 小时前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap