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

相关推荐
不能只会打代码4 分钟前
边缘视频分析平台的架构设计与性能优化——从750ms到190ms的调优之路
java·spring boot·redis·性能优化·边缘计算·物联网竞赛
xufengzhu3 小时前
第三方 Python 库 redis-py + hiredis 的使用
开发语言·redis·python
轻刀快马6 小时前
跨越软硬件的共鸣(二):从 Cache 写策略看 Redis 与 DB 的一致性博弈
java·开发语言·redis·计算机组成原理
lazy H8 小时前
Spring Boot 项目如何连接 Redis?新手入门配置和常见错误总结
ide·spring boot·redis·后端·学习·intellij-idea
木雷坞9 小时前
Firecrawl Docker Compose 自托管排查:镜像、Redis、队列和 Playwright
redis·docker·容器·firecrawl
柏舟飞流10 小时前
Spring Boot 进阶实战:整合 MyBatis、Redis、JWT,搭一个更像真实项目的后端服务
spring boot·redis·mybatis
南部余额11 小时前
Canal解决MySQL与Redis数据一致性问题
数据库·redis·mysql·canal·数据·数据同步
典学长编程12 小时前
Redis分布式缓存超详细教学(微服务版)!
redis·微服务·持久化·主从复制·redis哨兵集群
uoKent13 小时前
Redis环境搭建与redis-cli基础操作
数据库·redis·缓存
IT策士1 天前
Redis 从入门到精通:性能调优与多语言客户端对比
数据库·redis·缓存