AI 助理
备案 控制台
开发者社区 云原生 中间件 文章 正文

Redis从入门到精通之底层数据结构简单动态字符串(SDS)详解

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
推荐场景:
阿里云宣布 Serverless 应用引擎 SAE2.0 将公测上线,多款产品全新升级
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
简介: SDS是Redis中的一种字符串类型,它是一种二进制安全的字符串,由简单动态字符串(SDS)实现。SDS支持多种数据结构,其中字符串(String)是最常用的一种数据结构之一。SDS的优点在于它可以避免C字符串常见的问题,比如缓冲区溢出和内存泄露等。SDS的常数复杂度获取字符串长度和杜绝缓冲区溢出可以避免使用strlen和strcat函数时的一些问题。同时,SDS的空间预分配和惰性空间释放两种策略可以减少修改字符串的内存重新分配次数。SDS也是二进制安全的,因为它不是以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束。SDS还兼容部分C字符串函数

redis高阶篇.jpg

大家好,我是冰点,今天我们聊一下Redis底层数据结构简单动态字符串(SDS)。以及对比一下不同版本Redis在此处的实现。

Redis是一个快速、开源、内存数据库,它是一个基于键值对的存储系统,由Salvatore Sanfilippo开发。Redis支持多种数据结构,其中字符串(String)是最常用的一种数据结构之一。在Redis中,字符串是由简单动态字符串(SDS)实现的。本文将详细介绍SDS的内部实现原理、优势以及在Redis中的应用。图片来源网络
image.png
redis底层数据结构

1.原理解析

1.1.SDS的内部实现原理

image.png
redis6.x版本底层数据结构

1.1.1 Redis 6.0版本和Redis5.0对比

Redis 6.0版本中,对于SDS的底层数据结构进行了升级。除了原有的SDS类之外,还有四个新的类:sdshdr8、sdshdr16、sdshdr32、sdshdr64。这些类的命名与其中的成员变量类型相关,分别表示使用8位、16位、32位、64位的无符号整数存储字符串长度和容量。
image.png

1.1.2 redis6和redis5对比

Redis 6.0版本相比Redis 5.0版本在SDS底层数据结构上进行了一些改进和优化。Redis 6.0中的SDS仍然包含三个成员变量lenfreebuf,但是buf不再是一个字符数组,而是一个unsigned char类型的数组。此外,在Redis 6.0中新增了四个SDS类:sdsHdr5sdsHdr8sdsHdr16sdsHdr32。这四个类分别代表SDS字符串的头部数据结构,用于存储SDS字符串的长度和空闲空间,以及标记SDS字符串的类型。

Redis 6.0版本中的这些改进和优化可以提高SDS的效率和灵活性。通过使用unsigned char类型的数组来存储SDS字符串,可以更好地处理二进制数据和字符编码。而新增的四个SDS类可以更灵活地处理不同长度的SDS字符串,减少内存浪费。此外,为了提高效率,Redis 6.0版本中还对SDS的内存管理进行了优化,避免了频繁的内存分配和释放操作。

这样的设计可以根据实际情况选择更合适的底层数据结构,从而减少内存占用。例如,当存储的字符串长度较小时,可以选择使用sdshdr8或sdshdr16,而当存储的字符串长度较大时,则可以使用sdshdr32或sdshdr64

1.1.3 优势

SDS是Redis中的一种字符串类型,它是一种二进制安全的字符串,相比于C语言中的字符串,SDS具有以下优点:

1.1.3.1. 动态扩容

SDS可以动态增加内存空间,避免了静态数组的大小限制。

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

SDS中的len属性表示字符串长度,可以在常数时间内获取字符串长度。

1.1.3.3. 杜绝缓冲区溢出

SDS会检查内存是否足够,避免了缓冲区溢出的问题。

1.1.3.4. 减少修改字符串的内存重新分配次数

SDS采用惰性空间释放和空间预分配的策略,可以减少修改字符串的内存重新分配次数。

1.1.3.5. 二进制安全

SDS不以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束,所以支持存储任何二进制数据。
关于二进制安全我引用一个网友的图片更形象
C语言是判断空字符('\0')去判断一个字符的长度的,但是有很多数据结构经常会穿插空字符在中间,比如图片,音频,视频,压缩文件的二进制数据,就比如下面这个单词,只能识别前面的 不能识别后面的字符。
image.png

Redis就不存在这个问题了,他不是保存了字符串的长度嘛,他不判断空字符,只判断长度,所以redis也经常被拿来保存各种二进制数据

1.1.3.6. 兼容部分C字符串函数

SDS可以重用C语言库中的一部分函数。
SDS的实现位于Redis的源代码中的src/sds.h和src/sds.c中。SDS的总体结构包括头部sdshdr和存储用户数据的buf,其中用户数据后总跟着一个\0。SDS有四种不同的头部,分别是sdshdr8、sdshdr16、sdshdr32和sdshdr64,其中len属性表示字符串长度,buf[]数组用来保存字符串的每个元素,alloc属性表示整个SDS除过头部与末尾的\0,剩余的字节数,flags始终为一字节,以低三位标识着头部的类型,高5位未使用。

下面是SDS的头部结构体示例:

struct sdshdr {
    uint32_t len;    //字符串长度
    uint32_t alloc;  //字符串空间大小
    unsigned char flags; //表示sds的类型(8位)
    char buf[];  //用于存储字符串数据
};

image.png

SDS的头部结构体中,len和alloc是SDS的关键属性,它们分别表示字符串的长度和分配的空间大小。对于一个SDS字符串,其实际长度可以通过len属性来获取,而其当前分配的空间大小则可以通过alloc属性来获取。
image.png

SDS支持的最大长度是2^32字节,因此len和alloc都是32位无符号整数。SDS的len属性不仅用于表示字符串的长度,还用于记录buf数组中已使用的字节数,因此SDS的实际长度可能比len属性的值要小。

SDS的优点在于它可以避免C字符串常见的问题,比如缓冲区溢出和内存泄露等。SDS的常数复杂度获取字符串长度和杜绝缓冲区溢出可以避免使用strlen和strcat函数时的一些问题。同时,SDS的空间预分配和惰性空间释放两种策略可以减少修改字符串的内存重新分配次数。SDS也是二进制安全的,因为它不是以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束。SDS还兼容部分C字符串函数,可以重用C语言库中的一部分函数。

2.SDS在Redis中的应用

SDS是Redis中最常用的底层数据结构之一,它被广泛应用于各种场景中,比如缓存、计数器、分布式锁等。在Redis中,SDS不仅作为字符串类型的基础实现,还被应用于其他数据结构中。

2.1. 字符串类型

在Redis中,字符串类型是最常用的数据结构之一,它可以用于存储各种类型的数据,比如整数、浮点数、二进制数据等。字符串类型中的字符串值是由SDS实现的,它可以动态扩容,避免了静态数组的大小限制。SDS还可以减少修改字符串的内存重新分配次数,从而提高了性能。

SDS在Redis中的应用非常广泛,它作为字符串类型的基础实现,还被应用于其他数据结构中。SDS的优点在于它可以避免C字符串常见的问题,比如缓冲区溢出和内存泄露等。SDS的常数复杂度获取字符串长度和杜绝缓冲区溢出可以避免使用strlen和strcat函数时的一些问题。同时,SDS的空间预分配和惰性空间释放两种策略可以减少修改字符串的内存重新分配次数。SDS也是二进制安全的,因为它不是以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束。SDS还兼容部分C字符串函数,可以重用C语言库中的一部分函数。

2.2.杜绝缓冲区溢出

字符串拼接是我们经常做的操作,在C和Redis中一样,也是很常见的操作,但是问题就来了,C是不记录字符串长度的,一旦我们调用了拼接的函数,如果没有提前计算好内存,是会产生缓存区溢出的。

比如本来字符串长这样:
image.png

现在需要在后面拼接 ,但是没计算好内存,结果就可能这样了:

image.png

3. SDS的优化技巧

在使用SDS时,还有一些优化技巧可以提高性能:

3.1. 尽量避免频繁修改SDS的值

SDS的修改操作会引起内存重新分配,因此频繁修改SDS的值会导致性能下降。如果需要频繁修改SDS的值,可以考虑使用缓存等技术来避免频繁的修改操作。

3.2. 使用API操作SDS

SDS提供了一些API操作,比如sdscat、sdscmp、sdsnew等,使用这些API操作可以避免直接操作SDS的buf数组,从而提高代码的可读性和可维护性。

3.3. 避免使用大量的短字符串

空间预分配策略会分配一定的额外空间,用于存储未来可能的扩展。如果使用大量的短字符串,会浪费SDS的空间预分配策略,因为大量的短字符串可能占用预分配的空间,而未来可能需要更多的空间来存储更长的字符串。因此,如果需要存储大量的短字符串,可以考虑使用其他数据结构,比如哈希表或者列表。

3.4. 避免使用过大的SDS

最大长度是2^32字节,因此如果需要存储非常大的字符串,可以考虑使用其他的存储方式,比如文件系统或者分布式存储系统。

3.5. 使用SDS的优点

SDS的优点在于它可以避免C字符串常见的问题,比如缓冲区溢出和内存泄露等。SDS的常数复杂度获取字符串长度和杜绝缓冲区溢出可以避免使用strlen和strcat函数时的一些问题。同时,SDS的空间预分配和惰性空间释放两种策略可以减少修改字符串的内存重新分配次数。SDS也是二进制安全的,因为它不是以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束。SDS还兼容部分C字符串函数,可以重用C语言库中的一部分函数。

4.总结

SDS是Redis中的一种字符串类型,它是一种二进制安全的字符串,由简单动态字符串(SDS)实现。SDS支持多种数据结构,其中字符串(String)是最常用的一种数据结构之一。SDS的优点在于它可以避免C字符串常见的问题,比如缓冲区溢出和内存泄露等。SDS的常数复杂度获取字符串长度和杜绝缓冲区溢出可以避免使用strlen和strcat函数时的一些问题。同时,SDS的空间预分配和惰性空间释放两种策略可以减少修改字符串的内存重新分配次数。SDS也是二进制安全的,因为它不是以空字符串来判断字符串是否结束,而是以len属性表示的长度来判断字符串是否结束。SDS还兼容部分C字符串函数,可以重用C语言库中的一部分函数。

在Redis中,SDS不仅作为字符串类型的基础实现,还被应用于其他数据结构中。使用SDS时,可以避免频繁修改SDS的值,使用API操作SDS,避免使用大量的短字符串,避免使用过大的SDS,充分利用SDS的优点,提高代码的性能和可读性。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
冰点.
目录
相关文章
nanshaws
|
6天前
|
缓存 NoSQL Java
springboot的缓存和redis缓存,入门级别教程
本文介绍了Spring Boot中的缓存机制,包括使用默认的JVM缓存和集成Redis缓存,以及如何配置和使用缓存来提高应用程序性能。
nanshaws
33 1
springboot的缓存和redis缓存,入门级别教程
何雨晨
|
3天前
|
存储 消息中间件 NoSQL
Redis 入门 - C#.NET Core客户端库六种选择
Redis 入门 - C#.NET Core客户端库六种选择
何雨晨
25 8
木子0204
|
2天前
|
消息中间件 存储 缓存
redis支持的数据结构
redis支持的数据结构
木子0204
9 2
杀死一只知更鸟debug
|
19天前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
杀死一只知更鸟debug
29 0
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
nanshaws
|
6天前
|
NoSQL Redis C++
Redis的实现五:二叉堆的数据结构和TTL、c,c++的实现
这篇文章详细探讨了二叉堆的数据结构及其在C和C++中的实现,特别强调了二叉堆在Redis中实现TTL(生存时间)功能的重要性,并通过代码示例展示了如何在Redis中使用二叉堆来管理键的过期时间。
nanshaws
16 0
xjb1121
|
2月前
|
存储 监控 NoSQL
redis数据结构-HyperLogLog
redis数据结构-HyperLogLog
xjb1121
38 1
热爱技术的小郑
|
2月前
|
SQL 存储 NoSQL
Redis6入门到实战------ 一、NoSQL数据库简介
这篇文章是关于NoSQL数据库的简介,讨论了技术发展、NoSQL数据库的概念、适用场景、不适用场景,以及常见的非关系型数据库。文章还提到了Web1.0到Web2.0时代的技术演进,以及解决CPU、内存和IO压力的方法,并对比了行式存储和列式存储数据库的特点。
热爱技术的小郑
61 16
Redis6入门到实战------ 一、NoSQL数据库简介
热爱技术的小郑
|
2月前
|
NoSQL 算法 安全
Redis6入门到实战------ 四、Redis配置文件介绍
这篇文章详细介绍了Redis配置文件中的各种设置,包括单位定义、包含配置、网络配置、守护进程设置、日志记录、密码安全、客户端连接限制以及内存使用策略等。
热爱技术的小郑
64 9
Redis6入门到实战------ 四、Redis配置文件介绍
热爱技术的小郑
|
2月前
|
NoSQL Redis 数据安全/隐私保护
Redis6入门到实战------ 二、Redis安装
这篇文章详细介绍了Redis 6的安装过程,包括下载、解压、编译、安装、配置以及启动Redis服务器的步骤。还涵盖了如何设置Redis以在后台运行,如何为Redis设置密码保护,以及如何配置Redis服务以实现开机自启动。
热爱技术的小郑
98 9
Redis6入门到实战------ 二、Redis安装
热爱技术的小郑
|
2月前
|
NoSQL Java Redis
Redis6入门到实战------思维导图+章节目录
这篇文章提供了Redis 6从入门到实战的全面学习资料,包括思维导图和各章节目录,涵盖了NoSQL数据库、Redis安装配置、数据类型、事务、持久化、主从复制、集群等核心知识点。
热爱技术的小郑
35 3
Redis6入门到实战------思维导图+章节目录
云原生

中间件

热门文章

最新文章

  • 1
    Java编码技巧之高效代码50例
  • 2
    Kafka、RabbitMQ、RocketMQ消息中间件的对比—— 消息发送性能
  • 3
    首届阿里巴巴中间件技术峰会资料回顾
  • 4
    Nginx 外的另一选择,轻量级开源 Web 服务器 Tengine 发布新版本
  • 5
    阿里电商架构演变之路
  • 6
    开源技术精粹:深入解析阿里消息中间件RocketMQ
  • 7
    2017双11技术揭秘—阿里巴巴数据库技术架构演进
  • 8
    云栖开发者沙龙 - 数据库分库分表中间件(杭州站) 业内专家大咖齐聚,期待你的参与
  • 9
    开源 | 蚂蚁金服分布式中间件开源第二弹:丰富微服务架构体系
  • 10
    阿里架构总监一次讲透中台架构,13页PPT精华详解,建议收藏!
  • 1
    阿里云可观测 2024 年 9 月产品动态
    36
  • 2
    Android & iOS 使用 ARMS 用户体验监控(RUM)的最佳实践
    66
  • 3
    谷歌、火狐、Edge等浏览器如何使用ActiveX控件
    138
  • 4
    iLogtail 进化论:重塑可观测采集的技术边界
    60
  • 5
    Star 3w+,向更安全、更泛化、更云原生的 Nacos3.0 演进
    106
  • 6
    深入探索 RUM 与全链路追踪:优化数字体验的利器
    113
  • 7
    新场景、新能力,AI-native 时代的可观测革新
    84
  • 8
    首个云上 AI 原生全栈可观测平台来了!
    100
  • 9
    Star 4w+,Apache Dubbo 3.3 全新发布,Triple X 领衔,开启微服务通信新时代
    107
  • 10
    重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
    904
  • 相关课程

    更多
  • 大数据实战项目:反爬虫系统(Lua+Spark+Redis+Hadoop框架搭建)第二阶段
  • 大数据实战项目:反爬虫系统(Lua+Spark+Redis+Hadoop框架搭建)第三阶段
  • Redis入门实战演练
  • Go语言核心编程 - 数据结构和算法
  • 云数据库 Redis 版使用教程
  • Redis数据库入门
  • 相关电子书

    更多
  • Redis在唯品会的应用实践——架构演进与功能定制
  • ApsaraDB for Redis——与创客同行
  • Apache Flink 流式应用中状态的数据结构定义升级
  • 相关实验场景

    更多
  • 如何通过数据库Redis内网访问
  • Tair for Redis数据闪回:任意时间点数据恢复
  • 如何开通Redis的专属集群
  • 基于Redis实现在线游戏积分排行榜
  • 下一篇
    阿里云无影AI云电脑亮相 体验大幅升级

    深圳坪山网站建设公司沁阳优化网站排名费用多少西安网站优化排名余姚自适应网站建设优化建站南京网站关键词优化排名济南卫浴行业网站优化推广渠道南城电子网站优化哪个品牌好广州专业网站seo优化无锡网站优化费用多少网站优化怎么获取内容临夏网站seo优化昌平网站优化平台坪山网站建设推荐服务行业网站优化如何投放网站产品优化原来是易速达北京网站优化公司哪家好深圳教育网站优化软件马鞍山市网站优化哪家信誉好优化推广营销网站吴川网站优化软件优化网站排名比选云速捷看看url网站的优化建议萝岗网站的优化青浦区360网站优化平台无锡科技网站优化商丘网站搜索优化价格四川测量网站优化价格表哈尔滨优化网站30t云浮网站权重优化网站优化千牛帮做网站和优化香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

    深圳坪山网站建设公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化