Redis07 - Redis底层数据结构

server/2025/2/13 11:19:41/

Redis底层数据结构

文章目录

  • Redis底层数据结构
    • 一:对象机制详解
    • 二:SDS 简单动态字符串
    • 三:压缩列表
        • zipList结构
    • 四:跳表

一:对象机制详解

在这里插入图片描述

  • String类型 - 简单动态字符串SDS
  • List类型 - 双向链表 & 压缩列表
  • Set类型 - 哈希表和整数数组
  • zset类型 - 压缩列表和跳表
  • hash类型 - 压缩列表和哈希表

二:SDS 简单动态字符串

Redis 是用 C 语言写的,但是对于Redis的字符串,却不是 C 语言中的字符串(即以空字符\0结尾的字符数组)

它是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将 SDS 作为 Redis的默认字符串表示。

在这里插入图片描述

用于存储二进制数据的一种结构,具有动态扩容的特点,实现位于src/sds.hsds.c

sdshdr就是头部,buf是实际存储数据的地方,这个数据结构除了存储二进制数据之外,还能存储对应的字符串,在buf中,用户数据的后面总是跟着一个\0数据 + \0 = buf

在这里插入图片描述
SDS有五种不同的头部. 其中sdshdr5实际并未使用到. 所以实际上有四种不同的头部

在这里插入图片描述

  • len 保存了SDS保存字符串的长度
  • buf[] 数组用来保存字符串的每个元素
  • alloc分别以uint8, uint16, uint32, uint64表示整个SDS, 除过头部与末尾的\0, 剩余的字节数.
  • flags 始终为一字节, 以低三位标示着头部的类型, 高5位未使用

一般来说,SDS 除了保存数据库中的字符串值以外,SDS 还可以作为缓冲区(buffer):包括 AOF 模块中的 AOF 缓冲区以及客户端状态中的输入缓冲区

三:压缩列表

zipList结构

是为了提高效率而设计的一种特殊编码的双向链表,可以存储字符串或者整数

存储整数的时候是采用整数的二进制而不是字符串的方式

能在O(1)的时间中完成list的push和pop相关的操作

因为每一次的操作都要重新分配ziplist的内存,所以实际的时间复杂度和ziplist的内存使用量相关

在这里插入图片描述

  • zlbytes字段的类型是uint32_t, 这个字段中存储的是整个ziplist所占用的内存的字节数
  • zltail字段的类型是uint32_t, 它指的是ziplist中最后一个entry的偏移量. 用于快速定位最后一个entry, 以快速完成pop等操作
  • zllen字段的类型是uint16_t, 它指的是整个ziplit中entry的数量。这个值只占2bytes(16位):
    • 如果ziplist中entry的数目小于65535(216), 那么该字段中存储的就是实际entry的值
    • 若等于或超过65535, 那么该字段的值固定为65535
    • 但实际数量需要一个个entry的去遍历所有entry才能得到
  • zlend是一个终止字节, 其值为0xff. ziplist保证任何情况下, 一个entry的首字节都不会是255

四:跳表

跳表结构在 Redis 中的运用场景只有一个,那就是作为有序列表 (Zset) 的使用。

跳跃表的性能可以保证在查找,删除,添加等操作的时候在对数期望时间内完成,但是缺点就会比较耗费内存的空间,跳表是典型的时间换空间的应用

在这里插入图片描述

/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {sds ele; // 数据double score; // 得分struct zskiplistNode *backward; // 指针指向结点的前一个紧邻结点struct zskiplistLevel {struct zskiplistNode *forward; // 指向比自己得分高的某个结点unsigned int span; // forward字段指向的结点, 距离当前结点的距离} level[];
} zskiplistNode;typedef struct zskiplist {struct zskiplistNode *header, *tail;unsigned long length;int level;
} zskiplist;

设计核心

头节点不持有任何数据, 且其level[]的长度为32

每个结点

  • ele字段,持有数据,是sds类型
  • score字段, 其标示着结点的得分, 结点之间凭借得分来判断先后顺序, 跳跃表中的结点按结点的得分升序排列.
  • backward指针, 这是原版跳跃表中所没有的. 该指针指向结点的前一个紧邻结点.
  • level字段, 用以记录所有结点(除过头节点外);每个结点中最多持有32个zskiplistLevel结构. 实际数量在结点创建时, 按幂次定律随机生成. 每个zskiplistLevel中有两个字段
    • forward字段指向比自己得分高的某个结点(不一定是紧邻的), 并且, 若当前zskiplistLevel实例在level[]中的索引为X, 则其forward字段指向的结点, 其level[]字段的容量至少是X+1. 这也是上图中, 为什么forward指针总是画的水平的原因.
    • span字段代表forward字段指向的结点, 距离当前结点的距离. 紧邻的两个结点之间的距离定义为1.

http://www.ppmy.cn/server/167307.html

相关文章

贪心算法_翻硬币

蓝桥账户中心 依次遍历 不符合条件就反转 题目要干嘛 你就干嘛 #include <bits/stdc.h>#define endl \n using namespace std;int main() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); string s; cin >> s;string t; cin >> t;int ret 0;for ( i…

【读书笔记·VLSI电路设计方法解密】问题44:什么是代码覆盖率

代码覆盖率&#xff08;Code Coverage&#xff09;与测试平台的概念密切相关。它是衡量测试平台质量的一种指标。通过使用特定的测试平台&#xff0c;对以HDL&#xff08;或其他高级语言&#xff09;构建的模块进行代码覆盖率分析&#xff0c;可以记录RTL源代码中哪些行被执行&…

碰一碰发视频源码技术开发,支持OEM

一、引言 在当今数字化信息快速传播的时代&#xff0c;碰一碰发视频这种便捷的数据交互方式正逐渐走进人们的生活。从技术实现角度来看&#xff0c;其后台开发逻辑是确保整个功能稳定运行的关键。本文将深入剖析碰一碰发视频后台开发的核心逻辑&#xff0c;为开发者提供技术参…

变化检测相关论文可读list

一些用得上的&#xff1a; 遥感变化检测常见数据集https://github.com/rsdler/Remote-Sensing-Change-Detection-Dataset/ 代码解读&#xff1a;代码解读 | 极简代码遥感语义分割&#xff0c;结合GDAL从零实现&#xff0c;以U-Net和建筑物提取为例 NeurIPS2024: https://mp.w…

【vs2022配置cursor】

Cursor搭配cmake实现C程序的编译、运行和调试的参考地址 cursor下载地址 第一步&#xff1a; 电脑上按爪cmake 第二步&#xff1a;cursor 配置 安装中文 第三步环境变量&#xff1a; D:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.322…

数据结构:队列

1.概念&#xff1a; 和栈相反&#xff0c;队列是一种先进先出的线性表它只允许在标的一段进行插入&#xff0c;而在另一端进行删除元素。这和我们日常生活中的排队是一致的&#xff0c;即最早入队的元素最早离开。队列中允许插入的一端叫做队尾&#xff0c;允许删除的一端的叫…

【云安全】云原生-K8S- API Server 未授权访问

API Server 是 Kubernetes 集群的核心管理接口&#xff0c;所有资源请求和操作都通过 kube-apiserver 提供的 API 进行处理。默认情况下&#xff0c;API Server 会监听两个端口&#xff1a;8080 和 6443。如果配置不当&#xff0c;可能会导致未授权访问的安全风险。 8080 端口…

曝苹果2026年秋季推首款折叠iPhone

一、苹果折叠iPhone的发布背景与意义 在智能手机市场中&#xff0c;折叠屏手机近年来发展迅猛&#xff0c;成为行业的新趋势。苹果公司在这一领域的动作相对迟缓&#xff0c;但随着技术的不断成熟和市场需求的增长&#xff0c;苹果也终于准备推出首款折叠iPhone。这不仅是苹果自…