除仅用于字符串字面量的情况外,对于可以被修改值的字符串的表示,Redis底层并没有采用C语言传统的字符串表示,即以空字符结尾的字符数组,而是采用专门为其设计的简单动态字符串作为其默认字符串表示,其英文全称为Simple Dynamic String,简称SDS。除了用于保存数据库中字符串值外,SDS也可以用于缓冲区buffer,比如AOF中的缓冲区、客户端输入缓冲区等。本文,我们将详细研究简单动态字符串SDS的实现及其在性能等方面的独特之处。

注:内容总结于《Redis设计与实现》一书!

SDS实现

SDS整体结构如下:

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

可以看到,SDS依然依靠字节数组char buf[]来保存字符串,但是,它还保存了字节数组char buf[]中已使用和未使用字节数量len、free,而len的含义即SDS所保存的字符串长度,free的含义则是SDS剩余可以容纳字符串的长度。一个简单的示例如下:

上图所示的SDS,存储了字符串"Redis",其长度为5,同时尚有4个字节的空间未被利用。而且,你会发现,其实buf数组的大小实际为10,在字符串末尾还有一个表示空字符的'\0',为什么会这样呢?这就是SDS设计的巧妙之处,它为了能够直接重用C字符串函数库里的一些字符串常用函数,而这个空字符是SDS自动添加的,且不计算在len和free内,对用户而言是透明的。

SDS较C字符串的优点

SDS为什么要做以上设计呢,它对于C字符串而言,有哪些优点?

其相比较于C字符串的优点总结如下:

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

C字符串并不会记录字符串的长度,必须遍历整个字符串,对遇到的每个非空字符计数,直到遇到代表字符串结尾的空字符,才能计算出字符串长度,其时间复杂度为O(N),而SDS则直接获取len属性值即可获知字符串长度,其时间复杂度为O(1),而len属性是SDS相关函数自动完成的,对于用户而言是透明的。这个优点对任何一个,即使非常长的字符串反复执行STRLEN命令,也不会对系统性能产生影响,确保了获取字符串长度不会成为Redis的性能瓶颈。

2、杜绝缓冲区溢出

当修改或替换C字符串中的值时,C字符串由于不会记录本身长度,也不会预分配空间,会产生缓冲区溢出,甚至偷偷修改其他字符串内容的情况,如下图所示:

如果我们想在S1现有字符串基础上追加一个Cluster,而又不对S1进行内存重分配,那么这个操作会造成缓冲区溢出,同时会偷偷修改掉S2字符串的值。而SDS的空间分配策略则会避免缓冲区溢出的情况发生,它会先检查len和free,确保要追加、修改、替换的长度能够得到满足,如不满足,则会自动进行空间再分配,从而避免缓冲区溢出。

3、减少字符串修改内存重分配次数

显然,Redis是使用场景决定了存储于其内的字符串会频繁的被修改,而如果是在C字符串情况下,就会发生以下两种情况:

3.1、对于增长性字符串修改操作,程序每次都需要通过内存重分配来满足字符串空间要求,如果忘了,则会产生2中所说的缓冲区溢出;

3.2、对于缩短性字符串修改操作,程序需要通过内存重分配来释放不再使用的空间,如果忘了,则会产生内存泄露的问题。

而内存重分配算法比较复杂,且涉及到系统调用,通常是一种比较耗时的操作,而SDS则依靠空间预分配和惰性空间释放两种策略解决了上述两个问题,减少了频繁的空间重分配等,提供了系统性能。总结如下:

(1)空间预分配

如果SDS修改后,其长度小于1M,也就是len小于1M,则程序会分配与len属性同样大小的未使用空间,即len=free,buf实际大小则还要加1,因为有上述兼容C字符串库函数所使用的空字符;如果SDS修改后其长度大于等于1M,则程序每次会分配1M的未使用空间,此时free等于1M,buf实际大小也是还要加,原因同上。

(2)惰性空间释放

如果SDS字符串被缩短,未使用字节数增大,则SDS并不会使用内存重分配立即回收缩短后的未使用空间,而是记录在free属性中,等待将来使用,这样,惰性空间释放策略避免了SDS缩短字符串时所必须的内存重分配回收空间操作,为将来可能的增长操作使用,提高了Redis字符串处理的性能。同时,对于真正需要释放空间的情况,SDS则提供了专门的API,供用户使用,避免空间的持续浪费。

4、二进制安全

C字符串以空字符作为字符串结尾的特点,决定了其只能保存文本数据,而不能存储图片、视频、音频等二进制数据,而SDS通过len属性则避免了这一情况,使其可以存储诸如上述图片、视频、音频等任意格式的二进制数据。

5、兼容部分C字符串函数

buf中末尾自动追加的空字符实现了SDS可以兼容部分C字符串函数,比如对比strcasecmp、追加strcat等函数。

SDS与C字符串对比如下:

SDS简单总结如下:

《Redis设计与实现》阅读:Redis底层研究之简单动态字符串SDS相关推荐

  1. Redis源码阅读笔记(1)——简单动态字符串sds实现原理

    首先,sds即simple dynamic string,redis实现这个的时候使用了一个技巧,并且C99将其收录为标准,即柔性数组成员(flexible array member),参考资料见这里 ...

  2. 【redis源码学习】simple dynamic strings(简单动态字符串 sds)

    文章目录 接 化 sds 结构分析 基本操作 创建字符串 释放字符串 sdsMakeRoomFor 扩容 小tip:`__attribute__ ((__packed__))` 发 接 阅读源码之前, ...

  3. Redis源码初探(1)简单动态字符串SDS

    前言 现在面试可太卷了,Redis基本是必问的知识点,为了在秋招中卷过其他人(虽然我未必参加秋招),本菜鸡决定从源码层面再次学习Redis,不过鉴于本菜鸡水平有限,且没有c语言基础,本文不会对源码过于 ...

  4. Redis内部数据结构详解之简单动态字符串(sds)

    本文所引用的源码全部来自Redis2.8.2版本. Redis中简单动态字符串sds数据结构与API相关文件是:sds.h, sds.c. 转载请注明,本文出自:http://blog.csdn.ne ...

  5. 《Redis设计与实现》阅读笔记(二)--简单动态字符串

    简单动态字符串 Redis只在一些无需对字符串进行修改的地方使用C字符串,大部分时候使用简单动态字符串(simple dynamic string, SDS),字符串的抽象类型.二进制安全,可以存放任 ...

  6. Redis数据结构之简单动态字符串SDS

    Redis的底层数据结构非常多,其中包括SDS.ZipList.SkipList.LinkedList.HashTable.Intset等.如果你对Redis的理解还只停留在get.set的水平的话, ...

  7. Redis数据结构——简单动态字符串-SDS

    1.SDS简介: redis没有使用C语言传统的字符串表示(以空字符结尾的字符数组),而是自己构建了一种名为简单动态字符串(SDS)的抽象类型,并将SDS用作redis的默认字符串表示. 除了用来保存 ...

  8. Redis之简单动态字符串sds

    转载:https://segmentfault.com/a/1190000012262739 redis在处理字符串的时候没有直接使用以'\0'结尾的C语言字符串,而是封装了一下C语言字符串并命名为s ...

  9. Redis源码剖析(十)简单动态字符串sds

    在对象系统概述中发现,好像所有和字符串有关的内容都有sds的存在,实际上,它是Redis内部对于c字符串的封装,所谓c字符串,其实就是char *,在sds.h头文件中可以清楚的看到它的定义 //sd ...

  10. redis笔记_源码_简单动态字符串SDS

    参照:https://zcheng.ren/sourcecodeanalysis/theannotatedredissourcesds/#sds%E5%B0%8F%E7%BB%93 这里用char b ...

最新文章

  1. CES 2019开胃菜竟然是芯片,英特尔 英伟达 高通 华为 AMD已经开打!
  2. Kubernetes — 控制器
  3. IE11下载文件时出现文件名乱码
  4. GDCM:gdcm::Attribute的测试程序
  5. 国家开放大学2021春1338幼儿园教育质量评价题目
  6. C/C++之string类小结
  7. linux 指令引用变量,Linux之变量引用与命令替换
  8. linux修改永久ip地址,centos设置IP地址,永久修改ipv4
  9. Docker学习文档之二 搭建环境-Windows环境
  10. 为什么中小企业选择 SAP Business One?
  11. 现代汇编教材还是基于8086,对理解当今CPU(如i9)有帮助吗,还是教程太滞后?
  12. JavaScript高级使用(一)--参数Arguments对象
  13. Android各个版本API的区别
  14. java available_关于InputStream类的available()方法
  15. 获取level2行情接口的功能详解
  16. 设置matlab关联文件,matlab2014b怎样设置文件关联
  17. 同步时序逻辑电路功能分析之同步五进制加法计数器
  18. 共享计算机添加打印机后无法打印机驱动,打印机无法打印原因?打印机设置共享的方法...
  19. 今日头条下拉框推广,出效果付费
  20. Vue中使用Wangeditor富文本实现聊天发送文件驻留

热门文章

  1. python学习手册四版中文_Python学习手册(第4版) 中文版.pdf 全文免费
  2. 精品软件 推荐 TM2013 性能不好的电脑可以用这软件替代QQ
  3. 信息收集端口扫描工具masscan
  4. matlab spearman秩相关系数,matlab统计分析与应用_基于copula函数的蒙特卡洛模拟计算var matlab-其它文档类资源...
  5. 51单片机学习笔记_2 LED 模块
  6. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例38
  7. 凤凰os linux双系统,逍遥安卓模拟器双系统无缝连接完胜Remix、凤凰OS
  8. 荒野行动 android 鼠标,荒野行动键盘映射模拟器
  9. 三面头条,靠P9级算法分享的两本算法pdf书籍,轻松拿到offer
  10. fiddler证书无法安装详解