Redis 数据结构——SDS

【redis】sds数据结构 本文从源码介绍sds的数据结构。 sds是redis中对传统字符串的封装,在其上加入了长度等信息。用于redis中key等字符串类型数据的存储。 1 sds的数据结构 typedef char *sds; /* Note: sdshdr5 is never used, we just access the flags byte directly. * However is here t... 阅读详情

简单动态字符串(sds)

定义

Redis没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组),而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用作Redis的默认字符串表示。

struct sdshdr {
    //等于SDS所保存字符串的长度
    int len;
    //记录buf数组中未使用字节的数量
    int free;
    //字节数组,用于保存字符串
    char buf[];
};

 

  • free属性的值为0,表示这个SDS没有分配任何未使用空间。

  • len属性的值为5,表示这个SDS保存了一个五字节长的字符串。

  • buf属性是一个char类型的数组,数组的前五个字节分别保存了'R'、'e'、'd'、'i'、's'五个 字符,而最后一个字节则保存了空字符'\0'。

SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面,并且为空字符分配额外的1字节空间,以及添加空字符到字符串末尾等操作,都是由SDS函数自动完成的,所以这个空字符对于SDS的使用者来说是完全透明的。遵循空字符结尾这一惯例的好处是,SDS可以直接重用一部分C字符串函数库里面的函数。

SDS于C字符串的区别

常数复杂度获取字符串长度

因为C字符串并不记录自身的长度信息,所以为了获取一个C字符串的长度,程序必须遍历整个字符串,对遇到的每个字符进行计数,直到遇到代表字符串结尾的空字符为止,这个操作的复杂度为O(N)。

和C字符串不同,因为SDS在len属性中记录了SDS本身的长度,所以获取一个SDS长度的复杂度仅为O(1)。

设置和更新SDS长度的工作是由SDS的API在执行时自动完成的,使用SDS无须进行任何手动修改长度的工作。

杜绝缓冲区溢出

C字符串不记录自身长度带来的一个问题是容易造成缓冲区溢出(buffer overflow)。

两个字符串物理相邻存储,第一个字符串内容修改长度比之前长,就发生了缓冲区溢出,导致第二个字符串出错。

SDS的空间分配策略完全杜绝了发生缓冲区溢出的可能性:当SDS API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需的要求,如果不满足的话,API会自动将SDS的空间扩展至执行修改所需的大小,然后才执行实际的修改操作,所以使用SDS既不需要手动修改SDS的空间大小,也不会出现前面所说的缓冲区溢出问题。

减少修改字符串时带来的内存重分配次数

SDS通过未使用空间解除了字符串长度和底层数组长度之间的关联:在SDS中,buf数组的长度不一定就是字符数量加一,数组里面可以包含未使用的字节,而这些字节的数量就由SDS的free属性记录。

空间预分配

空间预分配用于优化SDS的字符串增长操作:当SDS的API对一个SDS进行修改,并且需要对SDS进行空间扩展的时候,程序不仅会为SDS分配修改所必须要的空间,还会为SDS分配额外的未使用空间。

  • 如果对SDS进行修改之后,SDS的长度(也即是len属性的值)将小于1MB,那么程序分 配和len属性同样大小的未使用空间,这时SDS len属性的值将和free属性的值相同。举个例 子,如果进行修改之后,SDS的len将变成13字节,那么程序也会分配13字节的未使用空间, SDS的buf数组的实际长度将变成13+13+1=27字节(额外的一字节用于保存空字符)。

  • 如果对SDS进行修改之后,SDS的长度将大于等于1MB,那么程序会分配1MB的未使用 空间。举个例子,如果进行修改之后,SDS的len将变成30MB,那么程序会分配1MB的未使 用空间,SDS的buf数组的实际长度将为30MB+1MB+1byte。

惰性空间释放

惰性空间释放用于优化SDS的字符串缩短操作:当SDS的API需要缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,并等待将来使用。

通过惰性空间释放策略,SDS避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供了优化。

二进制安全

C字符串中的字符必须符合某种编码(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。

为了确保Redis可以适用于各种不同的使用场景,SDS的API都是二进制安全的 (binary-safe),所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、或者假设,数据在写入时是什么样的,它被读取时就是什么样。

Redis不是用数组来保存字符,而是用一系列二进制数据来保存。

兼容部分C字符串函数

虽然SDS的API都是二进制安全的,但它们一样遵循C字符串以空字符结尾的惯例:这些API总会将SDS保存的数据的末尾设置为空字符,并且总会在为buf数组分配空间时多分配一个字节来容纳这个空字符,这是为了让那些保存文本数据的SDS可以重用一部分<string.h>库定义的函数。

strcasecmp(sds->buf, "hello world");
strcat(c_string, sds->buf);

总结

C字符串SDS
获取字符串长度的复杂度O(N)获取字符串长度的复杂度O(1)
API是不安全的,可能造成缓冲区溢出API是安全的,不会造成缓冲区溢出
修改字符串长度N次必然需要执行N次内存重分配修改字符串长度N次最多需要执行N次内存重分配
只能保存文本数据可以保存文本或者二进制数据
可以使用所有<string.h>库函数可以部分所有<string.h>库函数

SDS API

函数作用时间复杂度
sdsnew创建一个包含给定 C 字符串的 SDS 。O(N), N 为给定 C 字符串的长度。
sdsempty创建一个不包含任何内容的空 SDS 。O(1)
sdsfree释放给定的 SDS 。O(1)
sdslen返回 SDS 的已使用空间字节数。这个值可以通过读取 SDS 的 len 属性来直接获得, 复杂度为 。
sdsavail返回 SDS 的未使用空间字节数。这个值可以通过读取 SDS 的 free 属性来直接获得, 复杂度为 O(1) 。
sdsdup创建一个给定 SDS 的副本(copy)。O(N) , N 为给定 SDS 的长度。
sdsclear清空 SDS 保存的字符串内容。因为惰性空间释放策略,复杂度为 O(1)。
sdscat将给定 C 字符串拼接到 SDS 字符串的末尾。O(N) , N 为被拼接 C 字符串的长度。
sdscatsds将给定 SDS 字符串拼接到另一个 SDS 字符串的末尾。O(N), N 为被拼接 SDS 字符串的长度。
sdscpy将给定的 C 字符串复制到 SDS 里面, 覆盖 SDS 原有的字符串。O(N) , N 为被复制 C 字符串的长度。
sdsgrowzero用空字符将 SDS 扩展至给定长度。O(N) , N 为扩展新增的字节数。
sdsrange保留 SDS 给定区间内的数据, 不在区间内的数据会被覆盖或清除。O(N) , N 为被保留数据的字节数。
sdstrim接受一个 SDS 和一个 C 字符串作为参数, 从 SDS 左右两端分别移除所有在 C 字符串中出现过的字符。O(M * N) , M 为 SDS 的长度, N 为给定 C 字符串的长度。
sdscmp对比两个 SDS 字符串是否相同。O(N) , N 为两个 SDS 中较短的那个 SDS 的长度。

比起C字符串,SDS具有以下优点:

1)常数复杂度获取字符串长度。

2)杜绝缓冲区溢出。

3)减少修改字符串长度时所需的内存重分配次数。

4)二进制安全。

5)兼容部分C字符串函数。

Redis系列之底层数据结构SDS SDS:Simple Dynamic String,翻译为简单动态字符串。SDS是一种用于存储二进制数据的数据结构,具有动态扩容的特点,代码位于src/sds.h和src/sds.c 阅读详情

相关推荐

64_Redis数据结构-SDS

本文主要介绍了 Redis 中的 SDS 数据结构。在 Redis 里,键常为字符串,值可为字符串或其集合,字符串应用广泛。由于 C 语言字符串存在长度获取不便、无法安全存储二进制数据及不可修改等问题,Redis 采用了自定义的 SDS 结构。

2301_82300081的博客 113

Redis数据结构:Set类型全面解析

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。相对于列表,集合也有两个特点:无序、不可重复 一个集合最多可以存储 2^32-1 个元素。概念和数学中个的集合基本类似,数学集合的概念是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。

栗筝i的博客 7507

【软件分享】天若OCR文字识别V4.48(翻译功能免费)

软件简介 吾爱破解论坛大佬天若幽心开发的一款OCR文字识别工具。支持快速截图识别,以及文本翻译。 下载地址 蓝奏云盘:点击下载 百度网盘:点击下载(密码:4dm4) 坚果云盘:点击下载 天翼云盘:点击下载 微软云盘:点击下载 使用教程 1、下载后对压缩包进行解压 2、双击天若OCR文字识别.exe 3、发现桌面右下角出现软件图标 4、双击软件图标即可开始截图识别 原帖地址 https://www.52pojie.cn/thread-692917-1-1.html ...

XavierJ的博客 1万+

redis set底层数据结构

set底层存储  redis的集合对象set的底层存储结构特别神奇,我估计一般人想象不到,底层使用了intset和hashtable两种数据结构存储的,intset我们可以理解为数组,hashtable就是普通的哈希表(key为set的值,value为null)。是不是觉得用hashtable存储set是一件很神奇的事情。  set的底层存储intset和hashtable是存在编码转换的,使用intset存储必须满足下面两个条件,否则使用hashtable,条件如下: 结合对象保存的所有元素都是整数

meser88的博客 6622

原生H5如何优雅拦截浏览器返回事件:全面屏侧滑退出的解决方案

本文深入探讨了在原生H5中如何优雅地处理浏览器返回事件,特别是针对全面屏手机侧滑返回手势的解决方案。核心是利用HTML5 History API,通过`history.pushState`方法在历史栈中插入记录,并监听`popstate`事件,从而实现在用户侧滑时平滑关闭全屏预览层而非直接退出页面,有效提升了移动端H5应用的原生交互体验。

i0j1k2l3m的博客 270

深入解析 ReDoc:从零构建高性能 API 文档的终极指南

ReDoc 是一个强大的开源工具,用于将 OpenAPI 规范转换为高质量、响应式的 API 文档。本文详细介绍了如何使用 ReDoc 构建和自定义 API 文档,包括如何编写支持 OpenAPI 的 API 注解、配置 HTML 页面以加载文档,以及如何利用 ReDoc 的高级功能进行定制。通过实例代码,您将学会如何灵活地展示 API 文档,提升用户体验。无论是初学者还是经验丰富的开发者,都能从本文中获得实用的技巧与方案,帮助快速搭建符合需求的 API 文档界面。

楠搏万的博客 4631

Redis五种数据结构(String List Set ZSet Hash)详解

比如字符串”32”,如果按照字符数组来解释,它包含两个字符,它们的ASCII码分别是0x33和0x32。而value则比较复杂,为了在同⼀个dict内能够存储不同类型的value,这就需要⼀个通⽤的数据结构,这个通用的数据结构就是robj,全名是redisObject。String的内部存储结构⼀般是SDS(Simple Dynamic String,可以动态扩展内存),但是如果⼀个String类型的value的值是数字,那么Redis内部会把它转成long类型来存储,从⽽减少内存的使用。

coderge's 优快云 Blog. 2039

Zemax操作41--公差分析(一)

zemax公差

lzy750750的博客 5973

redis基本数据结构-set

redis 的 set 数据结构是一个无序的集合,可以存储不重复的元素。适合于多种应用场景,尤其是在需要去重、快速查找和集合运算的场合。无序性:元素在set中没有特定的顺序;唯一性:set中的元素是唯一的,不能重复。其中还有一个比较重要的特性就是高效性。因为redis 的 Set 数据结构是基于哈希表(hash table)实现的,这也是为什么对元素的添加、删除和查找操作的时间复杂度都是 O(1) 的原因。哈希函数:哈希表使用哈希函数将元素映射到一个数组的索引中。

qq_40840571的博客 2591

设备接入与APP(应用程序)接入华为云iotDA平台的详细操作步骤及获取方式

设备及APP(应用程序) 登录 IoTDA 平台所需的 入场与操作清单内容,提供逐项详细操作步骤和获取方式,并穿插贴士便于理解与实际操作落地。内容基于 华为云 IoTDA 控制台 和 IAM 控制台 的实际使用路径整理。

hy行者勇哥的博客 3059

PCL 计算点云的体积密度(C++详细过程版)

本文提出了一种基于点云体积密度的计算与可视化方法。算法通过KdTree搜索每个点的邻域,利用球体积公式计算单位体积内的点数作为密度值,并存储在点云强度属性中。代码实现了点云读取、密度计算和可视化功能,使用PCL库完成邻域搜索和密度渲染。结果显示,该方法能有效反映点云密度分布,为后续点云处理提供密度特征参考。文章附有完整C++代码实现和可视化效果图,适用于点云密度分析和特征提取应用。

点云侠的博客 308

【Redis】数据结构 - Set

Set 数据结构中元素的数量不受限制,但是由于 Redis 在内部使用哈希表实现 Set 数据结构,因此当 Set 中元素的数量较大时,哈希表的内存开销也会相应增加。注意 Set 中元素的大小:由于 Redis 在内部使用哈希表实现 Set 数据结构,因此当 Set 中元素的大小较大时,哈希表的内存开销也会相应增加。需要注意的是,在使用 Redis 的 Set 数据结构时,应该遵循 Redis 的规范和约定,使用合适的命令和操作方法,并注意数据类型转换和内存管理等问题。

比嗨皮兔 1265

huggingface使用git上传model或者Dataset到HF,当然也可以上传代码,以及大文件,很哇塞!!!

huggingface使用git上传model或者Dataset到HF,当然也可以上传代码,以及大文件,很哇塞!!! 第一次使用时,需要使用设置系统全局的huggingface token,这。点击huggingface首页右上角的头像 → settings → access tokens,创建一个write权限的token,名字可以随便取。

拥抱具身智能,昇腾Ascend C 3105

Redis中SDS的数据结构

Redis中的SDS详解

2301_81453175的博客 1309

基于ESP32的室内空气质量检测系统开发

随着环境污染问题的日益严重,室内空气质量的监测变得越来越重要。室内空气质量的好坏直接影响到人们的健康,尤其是对于在封闭空间长时间待着的人群。为此,基于ESP32的室内空气质量检测系统应运而生。ESP32作为一款集成了Wi-Fi和蓝牙的高性能微控制器,为嵌入式开发提供了良好的平台,适用于构建各种智能硬件设备。本博客将详细介绍如何基于ESP32开发一个室内空气质量检测系统。系统可以实时监测空气中的温度、湿度、二氧化碳浓度、甲醛浓度等指标,并通过Wi-Fi将数据传输到云端或移动设备,方便用户随时查看空气质量情况。

2201_76125393的博客 832

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Redis底层数据结构——SDS

7//sdshdr类型掩码,3//sdshdr类型位数因为sdshdr只有4种类型,用3个bit位即可表示10241024//sds字符串最大预分配空间,1MB。

qq_41637232的博客 1883

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Redis数据结构之——sds

Redis数据结构之——sds

weixin_46935110的博客 5773

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Redis内部数据结构详解(2)——sds

我们知道,在C语言中,字符串是以’\0’字符结尾(NULL结束符)的字符数组来存储的,通常表达为字符指针的形式(char *)。它不允许字节0出现在字符串中间,因此,它不能用来存储任意的二进制数据。我们可以在sds.h中找到sds的类型定义肯定有人感到困惑了,竟然sds就等同于char *?我们前面提到过,sds和传统的C语言字符串保持类型兼容,因此它们的类型定义是一样的,都是char *。在有些情况下,需要传入一个C语言字符串的地方,也确实可以传入一个sds。但是,sds和char *并不等同。

smart_an的专栏 847

Redis底层数据结构之SDS

Redis 中的 SDS(Simple Dynamic String,简单动态字符串)是 Redis 用于存储字符串值的底层实现,是对 C 语言传统字符串(以 null 结尾的字符数组)的改良,内部结构类似于 C 语言的字符数组,但额外存储了字符串长度和分配空间大小,避免了 C 字符串的缺陷。SDS用于解决 C 字符串的一些限制和安全性问题, 具有动态扩容的特点. 其实现位于src/sds.h与src/sds.c中。

xiong_tai的博客 1614

redis的基础数据结构之 sds

防写完博客待审核,先发个博客占坑 防写完博客待审核,先发个博客占坑 防写完博客待审核,先发个博客占坑

a158372582的博客 1278

Redis之SDS数据结构

简单动态字符串SDS(Simple Dynamic String)

四问四不知的博客 1067

Redis数据结构源码解析之SDS

1.前言 Hello,欢迎大家来到《 Redis 数据结构源码解析系列》,在《Redis为什么这么快?》一文中敖丙说过 Redis 速度快的一个原因就是其简单且高效的数据结构。 本系列文章面向各个阶段的 Coder 们,新手也不用怕。每一篇文章敖丙都将从命令实战入门入手,随后深入源码解析,最后面试题回顾这三个方向上给各位看官一一介绍。 2.SDS命令实战[初来乍到] SDS 是 Redis 中最简单的数据结构。Redis 中所有的数据结构都是以唯一的 key 字符串作为名称,根据 key 获取value,

带翅膀的猫的博客 1842

redis数据结构——SDS

在使用中,redis有五种对象:String、Hash、List、Set、Sorted Set 那么他们在底层是怎么实现的呢?最近阅读了《Redis设计与实现》一书,参考此书阅读了Redis源码,现在记录在此。 在redis中有以下几种数据结构:SDS、链表、字典、跳跃表、整数集合、压缩列表,它们在不同的条件下实现了redis的五种对象。 在这一篇中,记录SDS相关内容。源码来自redis-...

bettyF的博客 317

一篇带你搞懂Redis数据结构之SDS

SDS巧妙的利用空间换时间的思想,虽然额外牺牲了一些空间,但是换来的是在高频场景下更佳优异的性能表现以及更好的兼容性。希望这篇文章能对大家在日常工作中有所启发。

wdj_yyds的博客 1557

redis基础知识:数据结构SDS

redis的string数据类型对应的sds数据结构,包含设计思路

dylan的博客 933
上一篇: MySQL 简单聊聊并发控制、事务及多版本并发控制(MVCC)
下一篇: Redis 数据结构——链表
楚瑞涛
博客等级 码龄9年 57粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值