当前位置: 首页 > article >正文

Redis7底层数据结构解析

redisObject

在 Redis 的源码中,Redis 会将底层数据结构(如 SDS、hash table、skiplist 等)统一封装成一个对象,这个对象叫做 redisObject,也简称 robj。

typedef struct redisObject {unsigned type : 4;      // 数据类型(string, list, set, zset, hash)unsigned encoding : 4;  // 编码方式(raw, int, hashtable, skiplist 等)unsigned lru : 24;      // LRU 时间戳或 LFU 信息int refcount;           // 引用计数void *ptr;              // 指向实际数据的指针
} robj;

string

string数据的类型,会根据value的类型不同,有以下⼏种处理⽅式

  • int : 如果value可以转换成⼀个long类型的数字,那么就⽤int保存value。只有整数才会使⽤int,如果是浮点数,Redis内部其实是先将浮点数转化成字符串,然后保存
    在这里插入图片描述

  • embstr : 如果value是⼀个字符串类型,并且⻓度⼩于44字节的字符串,那么Redis就会⽤embstr保存。代表embstr的底层数据结构是SDS(Simple Dynamic String 简单动态字符串)

embstr字⾯意思就是内嵌字符串。 所谓内嵌的核⼼,其实就是将新创建的SDS对象直接分配在对象⾃⼰的内存后⾯。这样内存读取效率明显更⾼。

SDS其实是⼀段不可修改的字符串,redis定义好了不同长度的sds。这意味着如果使⽤APPEND之类的指令尝试修改⼀个key的值,那么就算value的⻓度没有超过44,Redis也会使⽤⼀个新创建的raw类型,⽽不再使⽤原来的SDS。
在这里插入图片描述

  • raw :如果value是⼀个字符串类型,并且⻓度⼤于44字节,就会⽤raw保存。

raw类型其实相当于是兜底的⼀种类型。特殊的数字类型和⼩字符串类型处理完了后,就是raw类型了。raw类型的处理⽅式就是单独创建⼀个SDS,然后将robj的ptr指向这个SDS。\

在这里插入图片描述

HASH

如果field-value对的数据⽐较少,就⽤listpack。如果数据⽐较多,就⽤hashtable。

hash-max-listpack-entries 限制value⾥键值对的个数(默认512),hash-max-listpack-value 限制value⾥值的数据⼤⼩(默认64字节)。

  • listpack
    listpack是ziplist的升级版,ziplist每个entry会记录前节点的长度(用于反向遍历),在⼤于等于254字节的新节点加⼊到压缩列表的表头节点会触发连锁更新。listpack则改为了记录当前entry的长度,不受到前节点影响,不会触发连锁更新,也就不直接支持反向遍历
    ziplist在这里插入图片描述
    ziplist的entry结构
    在这里插入图片描述
    listpack
    在这里插入图片描述

  • hashtable
    dict构成了hash的整个value,dictEntry则是field-value,dictEntry内有下一个dictEntry的指针(c语言使用sizeof(struct 结构体名)可以获取结构体所占的长度)

hash底层数据结构总结

  1. hash底层更多的是使⽤listpack来存储value。
  2. 如果hash对象保存的键值对超过512个,或者所有键值对的字符串⻓度超过64字节,底层的数据结构就会由listpack升级成为hashtable。
  3. 对于同⼀个hash数据,listpack结构可以升级为hashtable结构,但是hashtable结构不会降级成为listpack。

List

list类型的数据,在Redis中还是以listpack+quicklist为基础保存的。

list-max-listpack-size -2每个list中包含的节点⼤⼩或个数。正数表示个数,负数-1到-5表示⼤⼩。
-5: max size: 64 Kb <-- not recommended for normal workloads
-4: max size: 32 Kb <-- not recommended
-3: max size: 16 Kb <-- probably not recommended
-2: max size: 8 Kb <-- good
-1: max size: 4 Kb <-- good

  • quicklist
    listpack可以看成是⼀个数组(Array)结构,查快改慢。与数组形成对⽐的是链表(List)结构。链表的节点之间只通过指针指向相关联的节点,修改只需要调整指针,但是只能沿着指针查找元素
    quicklist则是两者结合,整体上是list,而每个quickListNode又有数个listpack
    在这里插入图片描述

set

Redis底层综合使⽤intset+listpack+hashtable存储set数据。set数据的⼦元素也是<k,v>形式的entry。其中,key就是元素的值,value是null。

如果set的数据不是数字,并且数据的⼤⼩没有超过下⾯设定的阈值,就⽤listpack存储
如果数据⼤⼩超过了其中⼀个阈值,就改为使⽤hashtable存储。
set-max-listpack-entries 128 指素数量不超过 128 个
set-max-listpack-value 64 指字节长度不超过 64 字节

  • intset是一个紧凑的有序整数数组结构,支持自动升级为更大整数类型,插入时使用二分查找来保持元素不重复,用于存储 所有是整数 且 数量不大 的集合。
typedef struct intset {uint32_t encoding;   // 当前使用的整数编码(int16、int32、int64)uint32_t length;     // 当前元素个数int8_t contents[];   // 实际存储整数的区域(变长数组)
} intset;
  • 关于这三种数据结构之间如何转换,以set数据类型最为典型的sadd指令为例,会进⼊下⾯这个⽅法进⾏处理。

    在创建set元素时,就会根据⼦元素的类型,判断是⽤intset还是⽤listpack。
    在这里插入图片描述
    ⽽在添加元素时,也会根据参数判断是否需要转换底层编码
    在这里插入图片描述

ZSET

Redis底层综合使⽤listpack + skiplist两种结构来保存zset类型的数据。

数据的⼤⼩没有超过下⾯设定的阈值,就⽤listpack存储
如果数据⼤⼩超过了其中⼀个阈值,就改为使⽤skiplist存储。
zset-max-listpack-entries 128 指素数量不超过 128 个
zset-max-listpack-value 64 指字节长度不超过 64 字节

  • skiplist
    skiplist的优化思路是构建多层逐级缩减的⼦索引,⽤更多的索引来提升搜索的性能。
    在这里插入图片描述
typedef struct zskiplistNode {sds ele;               // 成员值(string)double score;          // 排序用分数struct zskiplistNode *backward; // 后退指针(用于反向遍历)struct zskiplistLevel {struct zskiplistNode *forward; // 指向下一节点unsigned int span;             // 跨越节点数(用于排名计算)} level[];             // 每一层的 forward/跨度信息
} zskiplistNode;

zskiplistLevel 存储了每一层,包括原始链表。

redis6/7数据结构差异

在这里插入图片描述

相关文章:

Redis7底层数据结构解析

redisObject 在 Redis 的源码中&#xff0c;Redis 会将底层数据结构&#xff08;如 SDS、hash table、skiplist 等&#xff09;统一封装成一个对象&#xff0c;这个对象叫做 redisObject&#xff0c;也简称 robj。 typedef struct redisObject {unsigned type : 4; // 数…...

Android 异步编程中协程的完整实战示例

一、全链路数据加载&#xff1a;网络请求 数据库缓存 在实际开发中&#xff0c;数据加载通常需要先检查本地缓存&#xff0c;若缓存失效则从网络获取&#xff0c;并将结果更新到本地。以下是完整的 MVVM 架构示例&#xff1a; 1. 项目结构 app/ ├── data/ …...

多部手机连接同一wifi的ip一样吗?

在家庭和办公环境中&#xff0c;多台手机同时连接同一个WiFi路由器已成为常态。不少用户会产生疑问&#xff1a;这些设备的IP地址会相同吗&#xff1f;下面就一起来了解一下吧。 一、多部手机连接同一WiFi的IP‌一样吗 多部手机连接同一WiFi时的IP地址是否相同&#xff0c;需要…...

大语言模型值ollama使用(1)

ollama为本地调用大语言模型提供了便捷的方式。下面列举如何在windows系统中快捷调用ollama。 winR打开运行框&#xff0c;输入cmd 1、输入ollama list 显示已下载模型 2、输入ollama pull llama3 下载llama3模型 3、 输入 ollama run llama3 运行模型 4、其他 ollama li…...

大模型应用开发之Langchain

一、框架简述 Langchain 是一个用于构建和管理 LLM 应用的开发框架。它为开发者提供了工具和接口&#xff0c;以便于更轻松地将大语言模型集成到应用程序中&#xff0c;并处理语言模型生成的响应、管理对话状态、执行链式调用、处理多步任务等。 二、Langchain主要模块 1、M…...

thc-ssl-dos:SSL 压力测试的轻量级工具!全参数详细教程!Kali Linux教程!

简介 THC-SSL-DOS 是一款用于验证 SSL 性能的工具。 建立安全的 SSL 连接需要服务器比客户端高 15 倍的处理能力。 THC-SSL-DOS 利用这种不对称特性&#xff0c;通过使服务器过载并使其断网。 此问题影响当今所有 SSL 实现。供应商自 2003 年以来就已意识到这个问题&#x…...

什么是内网ip证书

内网IP证书是一种基于公钥基础设施&#xff08;PKI&#xff09;技术的数字证书&#xff0c;专门用于保护企业内部网络中通过IP地址访问服务的通信安全。以下是对内网IP证书的详细解析&#xff1a; 一、核心定义与用途 定义&#xff1a;内网IP证书是SSL/TLS证书的一种特殊类型…...

【速通RAG实战:进阶】17、AI视频打点全攻略:从技术实现到媒体工作流提效的实战指南

一、AI视频打点的技术底层与数据处理流程 (一)视频内容结构化的核心技术栈 AI视频打点的本质是将非结构化视频数据转化为带时间戳的结构化信息,其技术流程涵盖音视频处理、语音识别、自然语言处理三大核心模块,形成“数据采集-内容解析-智能标记-协同应用”的完整闭环。 …...

立控信息智能装备柜:科技赋能军队装备管理现代化

在军事装备管理领域&#xff0c;高效、安全、智能化的存储解决方案至关重要。传统的人工管理模式不仅效率低下&#xff0c;还容易因人为疏忽导致装备丢失或管理混乱。​LKONE智能装备柜凭借先进的物联网技术、生物识别安全系统和智能管理功能&#xff0c;为军队提供了一套高效、…...

【freertos-kernel】queue(发送)

文章目录 补充各种yeildTCB的xStateListItem和xEventListItem xQueueGenericSendprvCopyDataToQueueprvNotifyQueueSetContainervTaskInternalSetTimeOutStatevTaskSuspendAllxTaskResumeAllprvLockQueueprvUnlockQueueprvIncrementQueueTxLockvTaskPlaceOnEventListprvAddCurr…...

【华为云物联网】如何实现在 MQTT.fx 上模拟数据间隔上传一次,并按设定系数变动数据

虽然 MQTT.fx 本身不支持定时循环脚本发送消息,但可以通过以下方式 实现在 MQTT.fx 上模拟设备参数每隔 1 分钟上传一次,并按设定系数变动数据: ✅ 推荐方式:使用 Python 脚本+MQTT.fx 联动观察 你将用 Python 自动发送数据,MQTT.fx 订阅对应主题观察是否发送成功。 🧩…...

破解高原运维难题:分布式光伏智能监控系统的应用研究

安科瑞刘鸿鹏 摘要 高原地区光照资源丰富&#xff0c;具有发展分布式光伏发电的巨大潜力。然而&#xff0c;该地区复杂的气候环境、地形地貌和运维条件对光伏电站的运行与维护带来严峻挑战。本文结合Acrel1000DP分布式光伏监控系统的技术特点和典型应用案例&#xff0c;探讨其…...

图标变白,开始菜单栏无法打开程序(以jupyter为例)

不知道是本人删了一些东西导致的还是什么原因&#xff0c;总之现在本人的jupyter只能通过命令行打开&#xff0c;以往我是从开始菜单栏打开。琢磨了一段时间&#xff0c;发现是.ico文件没有了。重新在网上下载图片&#xff0c;用网站图片转 ico 图标 - 锤子在线工具 转换一下格…...

大语言模型(LLM)入门 - (1) 相关概念

文章来自&#xff1a;大语言模型(LLM)小白入门自学项目-TiaoYu-1 GitHub - tiaoyu1122/TiaoYu-1: For People! For Freedom!For People! For Freedom! Contribute to tiaoyu1122/TiaoYu-1 development by creating an account on GitHub.https://github.com/tiaoyu1122/TiaoYu…...

行为型:访问者模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 1、核心思想 目的&#xff1a;数据结构稳定的情况下&#xff0c;解决数据与算法的耦合问题。适用于对象结构稳定但需频繁扩展操作的场景。 实现&#xff1a;在访问数据时根据数据类…...

C++数据结构 : 哈希表的实现

C数据结构 &#xff1a; 哈希表的实现 目录 C数据结构 &#xff1a; 哈希表的实现引言1. 哈希概念1.1 直接定址法1.2 哈希冲突1.3 负载因子 2. 哈希函数2.1 除法散列法/除留余数法2.2 乘法散列法&#xff08;了解&#xff09;2.3 全域散列法&#xff08;了解&#xff09; 3. 处…...

抖音电商客户端一面面经

抖音电商客户端一面面经 时间&#xff1a; 25.05.30 岗位&#xff1a; 抖音电商客户端开发工程师 形式&#xff1a; 技术一面 刚刚结束了字节跳动抖音电商客户端开发工程师岗位的技术一面&#xff0c;整体感觉考察范围非常全面&#xff0c;涵盖了基础、项目、算法、系统设计等…...

JavaScript 在 AcroForm 中的广泛应用

在Adobe表单(特别是SAP Interactive Forms by Adobe)中使用JavaScript的各种技巧和方法,下面这些代码片段可以帮助开发者更高效地处理表单逻辑和交互。 1. 获取数据内容 从上下文结构中获取数据 var LV_DATA = xfa.resolveNode("$record.IM_TEST.FIELDNAME").val…...

Socket编程之TCP套件字

基于的TCP套件字编程流程 1. Socket套接字 Socket是一个编程接口&#xff08;网络编程接口&#xff09;&#xff0c;是一种特殊的文件描述符&#xff08;write/read&#xff09;。Socket并不 仅限于TCP/IP Socket独立于具体协议的编程接口&#xff0c;这个接口位于TCP/IP四层…...

AD9268、AD9643调试过程中遇到的问题

Ad9268芯片 AD9268是一款双通道、16位、80 MSPS/105 MSPS/125 MSPS模数转换器(ADC)。AD9268旨在支持要求高性能、低成本、小尺寸和多功能的通信应用。双通道ADC内核采用多级差分流水线架构&#xff0c;集成输出纠错逻辑。每个ADC都具有宽带宽、差分采样保持模拟输入放大器&…...

Java-File类基本方法使用指南

Java-File类基本方法使用指南 一、File类基础概念1.1 什么是File类1.2 File类的构造函数 二、文件和目录的创建与删除2.1 创建文件 - createNewFile()2.2 创建目录 - mkdir() 和 mkdirs()2.3 删除文件或目录 - delete() 三、文件和目录的查询与判断3.1 存在性判断 - exists()3.…...

Python爬虫实战:研究PyQuery库相关技术

1. 引言 1.1 研究背景与意义 随着互联网的快速发展,网络上的数据量呈爆炸式增长。如何高效地从海量的网页数据中提取有价值的信息,成为当前信息技术领域的一个重要研究方向。网络爬虫作为一种自动获取网页内容的程序,能够按照一定的规则,自动地抓取万维网信息,在搜索引擎…...

第九篇:MySQL 安全加固与访问控制策略实战

数据库的安全不仅仅是防止外部入侵&#xff0c;更包括合理配置账户权限、日志审计、网络加密、配置加固等。本文将系统性梳理 MySQL 的安全机制与实战加固方法&#xff0c;助你构建安全可靠的数据库运行环境。 一、数据库安全风险面 数据库常面临的威胁&#xff1a; 弱口令或默…...

神经网络-Day40

目录 单通道图片的规范写法图像任务中的张量形状NLP任务中的张量形状1. **Flatten操作**2. **view/reshape操作** 总结彩色图片的规范写法 图像数据的格式以及模型定义的过程&#xff0c;和之前结构化数据的略有不同&#xff0c;主要差异体现在2处 模型定义的时候需要展平图像由…...

WindowServer2022下docker方式安装dify步骤

WindowServer2022下docker方式安装dify步骤&#xff08;稳定后考虑部署至linux中&#xff09; 教程&#xff1a;https://blog.csdn.net/qq_49035156/article/details/143264534 0、资源要求 ---windows&#xff1a;8核CPU、16G内存、200G500G存储 ---10.21.31.122/administra…...

Java五种方法批量处理List元素全解

Java:如何优雅批量处理List中的每个元素 一、场景分析&#xff1a;为什么需要批量处理List&#xff1f;二、核心方法&#xff1a;五种实现方式对比2.1 普通for循环&#xff08;最直接的方式&#xff09;代码示例&#xff1a;优缺点&#xff1a; 2.2 Java 8 replaceAll&#xff…...

springboot文件上传下载

基于ResponseEntity的下载响应 SpringBoot中&#xff0c;ResponseEntity类型可以精确控制HTTP响应&#xff0c;为文件下载提供完善的HTTP头信息。 RestController RequestMapping("/api/download") public class FileDownloadController {GetMapping("/file/{…...

webpack CDN打包优化

CDN网络分发服务 请求资源时最近的服务器将缓存内容交给用户 体积较大且变动不多的文件存在CDN文件中 react react-dom资源 // 添加自定义对于webpack的配置const path require(path) const { whenProd, getPlugin, pluginByName } require(craco/craco)module.exports {//…...

ARM内核一览

经常看介绍某某牛批芯片用的又是ARM什么核&#xff0c;看的云里雾里&#xff0c;所以简单整理整理。&#xff08;内容来自官网和GPT&#xff09; 1 ARM 内核总体分类 系列特点应用场景Cortex-M超低功耗、低成本、实时性嵌入式系统、微控制器、IoTCortex-R高可靠性、硬实时汽车…...

Rust 和 Python 如何混合使用

Rust 与 Python 可以通过多种方式混合使用&#xff0c;如 FFI 接口、PyO3 库、CFFI、CPython API、wasm 模块嵌入等。这种混合开发模式可结合 Rust 的性能优势与 Python 的开发效率。其中&#xff0c;PyO3 是目前最受欢迎的桥接工具&#xff0c;它允许使用 Rust 编写 Python 扩…...