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

redis源码分析之底层数据结构(一)-动态字符串sds

1.绪论

我们知道redis是由c语言实现的,c语言中是自带字符串的,但是为什么redis还要再实现自己的动态字符串呢,这种动态字符串的底层数据结构是怎样的呢?接下来我们带着这些问题来看一看redis中的动态字符串sds。

2.sds的组成

struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {//字符数组的长度uint16_t len; /* used *///整个sds字符串的大小uint16_t alloc; /* excluding the header and null terminator *///表示是5种sds字符串中的哪一种unsigned char flags; /* 3 lsb of type, 5 unused bits *///真正存储数据的地方char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};

可以看出redis中sds是一个动态数组,它由长度+sds占据内存大小+sds的类型+加一个数组组成。如果用图表示如下:

可以看出redis的sds和java中的ArrayList是类似的。

3.sds的优点

为什么redis需要重新实现一个字符串呢?主要有如下的几点考虑:

3.1.常数时间复杂度获取字符串长度

普通字符串以'\0'结尾,而sds存取了整个字符串占据多少个字符。所以普通字符串需要用o(n)的复杂度获取到字符串长度,而sds以o(1)的复杂度获取到字符串长度;

3.2.存储特殊符号\0

sds能够存储特殊符号\0',当时c语言原生的字符串以'\0'结尾,不能存储\0,保证二进制安全;

3.3.内存动态分配,防止杜绝缓冲区溢出

c语言原生字符串,内存一但分配,大小便固定,比如在调用'append key'命令的时候,会实现字符串拼接的功能,如果超出缓冲器大小,会超出分配内存大小而报错;
但是sds实现了动态扩展的功能,在拼接前,会检查内存是否够用,如果不够用,便会进行动态扩容,而如果数组的剩余空间过多,便会进行缩容。

3.3.1 动态扩容

当新的字符串占用空间超出分配内存空间时,会进行动态分配,并且会提前考虑预分配一部分空间,防止内存的频繁分配问题。

3.3.2 动态缩容 

当已使用内存小于分配内存的部分比例时,会进行动态缩容,并且采用惰性释放的策略,不使用的数据并不会立即清除,而是等待有新的字符串写入的时候进行覆盖。

3.4.节约内存

在高版本的redis中,将存储字符数值分成了5类,分别是sdshdr5 、sdshdr8 、sdshdr16 、sdshdr32 、sdshdr64 ,redis会根据存储的字符内容来判断采用哪个中字符串尽显存储数据。比如如果用户写入的字符串只包含abcd这种英文字母,每个字符串用一个字节便能存储。sds便会考虑采用sdshdr8来进行存储.

4.总结

可以看出redis的sds其实就相当于java中的ArrayList,都具有动态扩容,缩容等功能。

5.参考

[1] 黄建宏 redis设计与实现

[2] https://juejin.cn/book/7144917657089736743/section/7144917738698326019

相关文章:

redis源码分析之底层数据结构(一)-动态字符串sds

1.绪论 我们知道redis是由c语言实现的,c语言中是自带字符串的,但是为什么redis还要再实现自己的动态字符串呢,这种动态字符串的底层数据结构是怎样的呢?接下来我们带着这些问题来看一看redis中的动态字符串sds。 2.sds的组成 struct __at…...

路由协议的优先级,以及管理距离 AD 和 metric 的区别

路由协议的优先级(Preference,即管理距离 Administrative Distance )一般为一个 0 到 255 之间的数字,数字越大则优先级越低。表一是通常情况下各路由协议的优先级规定: 表一:一般路由协议优先级 路由协议…...

力扣 24两两交换链表中节点

画图 注意有虚拟头结点 注意判断时先判断cur->next ! nullptr,再判断cur->next->next ! nullptr 注意末尾返回dumyhead->next,用新建result指针来接并返回 class Solution { public:ListNode* swapPairs(ListNode* head) {ListNode *dummyhead new …...

C# + halcon 联合编程示例

C# halcon 联合编程示例 实现功能 1.加载图像 2.画直线,画圆,画矩形, 画椭圆 ROI,可以调整大小和位置 3.实现找边,找圆功能 效果 开发环境 Visual Studio 2022 .NET Framework 4.8 halcondotnet.dll 查看帮助文档 项目结构 DL…...

【Git基本操作】添加文件 | 修改文件 | 及其各场景下.git目录树的变化

目录 1. 添加文件&add操作和commit操作 2. .git树状目录的变化 3. git其他操作 4. 修改文件 4.1 git status 4.2 git diff 1. 添加文件&add操作和commit操作 add操作:将工作区中所有文件的修改内容 添加进版本库的暂存区中。commit操作:…...

Aop切面编程(2)--代理模式

1、代理模式的理解:不修改A对象的代码的基础上,对A代码块进行拓展。通过创建ProxyA代理对象,拓展A对象并调用A对象的核心功能; 即:不修改对象的源码基础上,创建代理对象,进行功能的附加和增强&…...

Spring Boot(八十):Tesseract实现图片文字自动识别

1Tesseract 要实现图片转文字(OCR,Optical Character Recognition)功能,可以使用一些现有的OCR库,比如Google的Tesseract或者百度AI、阿里云OCR等云服务。 下面以Tesseract为例: Tesseract是一个开源文本识别 (OCR)引擎,是目前公认最优秀、最精确的开源OCR系统,用于…...

QT 图片处理

1.qt 图片控件 在Qt中,用于显示图片的控件主要是QLabel。以下是关于Qt图片控件的详细介绍: QLabel控件: QLabel是Qt中用于显示文本或图片的控件。在显示图片时,QLabel通过setPixmap()函数来设置要显示的图片。QPixmap代表Qt中的…...

Linux C++ 053-设计模式之模板方法模式

Linux C 053-设计模式之模板方法模式 本节关键字:Linux、C、设计模式、模板方法模式 相关库函数: 概念 模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新…...

【Python 项目】类鸟群:仿真鸟群

类鸟群:仿真鸟群 仔细观察一群鸟或一群鱼,你会发现,虽然群体由个体生物组成,但该群体作为一个整体似乎有它自己的生命。鸟群中的鸟在移动、飞越和绕过障碍物时,彼此之间相互定位。受到打扰或惊吓时会破坏编队&#xf…...

基于信号处理的PPG信号滤波降噪方法(MATLAB)

光电容积脉搏波PPG信号结合相关算法可以用于人体生理参数检测,如血压、血氧饱和度等,但采集过程中极易受到噪声干扰,对于血压、血氧饱和度测量的准确性造成影响。随着当今社会医疗保健技术的发展,可穿戴监测设备对于PPG信号的质量…...

新一代信息技术及应用

关于云计算的描述不正确的是( )。 A 云计算可以通过网络连接,用户通过网络接入“云”中并获得有关的服务,“云”内节点之间也通过内部的网络相连 B 云计算可以快速、按需、弹性服务,用户可以按照实际需求迅速获取或释放…...

SVN 解决冲突

SVN 解决冲突 1. 引言 在软件开发过程中,版本控制是一个至关重要的环节。SVN(Subversion)作为一个流行的版本控制系统,被广泛应用于团队协作中。然而,当多个开发者同时对同一部分代码进行修改时,冲突是不可避免的。本文将详细介绍如何在SVN中解决这些冲突,以便团队成员…...

机器人前沿--PalmE:An Embodied Multimodal Language Model 具身多模态大(语言)模型

首先解释这篇工作名称Palm-E,发表时间为2023.03,其中的Palm是谷歌内部在2022.04开发的大语言模型,功能类似ChatGPT,只是由于各种原因没有那样火起来,E是Embodied的首字母,翻译过来就是具身多模态大语言模型…...

编程语言都是哪些人开发出来的?为什么都是国外较小国家的人

编程语言都是哪些人开发出来的? 编程语言的开发者通常是来自计算机科学、软件工程、数学、物理学等领域的专家、学者和工程师。这些开发者具备深厚的编程技能、算法知识、系统设计能力以及创新思维,他们致力于创造出能够解决特定问题或满足特定需求的编…...

【前端速通系列|第二篇】Vue3前置知识

文章目录 1.前言2.包管理工具npm2.1下载node.js2.2配置 npm 镜像源2.3 npm 常用命令 3.Vite构建工具4.Vue3组件化5.Vue3运行原理 1.前言 本系列文章旨在帮助大家快速上手前端开发。 2.包管理工具npm npm 是 node.js中进行 包管理 的工具. 类似于Java中的Maven。 2.1下载nod…...

ES6 Module 的语法(十二)

ES6(ECMAScript 2015)引入了模块(Modules)的概念,使得JavaScript代码可以更容易地组织和复用。 1. export 关键字 命名导出 (Named Exports) 你可以使用 export 关键字导出多个变量、函数或类。 // module.js export…...

Redis 主从复制,哨兵与集群

目录 一.redis主从复制 1.redis 主从复制架构 2.主从复制特点 3.主从复制的基本原理 4.命令行配置 5.实现主从复制 6.删除主从复制 7.主从复制故障恢复 8.主从复制完整过程 9.主从同步优化配置 二.哨兵模式(Sentinel) 1.主要组件和概念 2.哨…...

CV05_深度学习模块之间的缝合教学(1)

1.1 在哪里缝 测试文件?() 训练文件?() 模型文件?(√) 1.2 骨干网络与模块缝合 以Vision Transformer为例,模型文件里有很多类,我们只在最后…...

【密码学】公钥密码的基本概念

在先前我写的密码学体制文章中谈到,现代密码学分为两大体制,介绍了一些有关对称密码体制诸如流密码和分组密码的内容。本文的主要内容则切换到公钥密码体制(又称非对称密码体制),简述了公钥密码体制的基本思想和应用方…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

微信小程序之bind和catch

这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...