简单动态字符串

SDS(simple synamic String)用作Redis默认字符串表示。C字符串只会作为字符串字面量用在一些无须对字符串进行修改的地方,例如打印日志等。

SDS定义

每个sds.h/sdshdr结构表示一个SDS值

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

SDS遵循C字符串以空字符结尾的惯例,保存空字符的一字节空间不计算再SDS的len属性,并且为空字符分配额外的1字节,添加空字符到字符串末尾等操作是由SDS函数自动完成的。好处是,可以直接重用一部分C字符串函数库里的函数。
sds结构图
在这里插入图片描述

SDS 与 C字符串的区别

获取字符串长度的复杂度

C字符串并不记录自身的长度信息,获去一个C字符串的长度,程序必须进行遍历整个字符串,对遇到的每个字符进行技术,直到遇到代表字符串结尾的空字符为止,这个操作的复杂度为O(N)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
而SDS在len的属性中记录了SDS本身的长度,所以获去一个SDS长度的复杂度仅为O(1)。
通过使用SDS而不是C字符串,Redis将获去字符串长度所需的复杂度O(N)降低到O(1),确保了获去字符串长度不会成为Redis的性能瓶颈。

杜绝缓冲区溢出

C字符串如果未分配足够的空间情况下
在这里插入图片描述
而SDS的空间分配策略杜绝了发生缓冲区溢出的可能性。当SDS API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改的需求,如果不满足的话,会自动将SDS空间扩展至所需的大小,然后才执行实际修改的操作,所以SDS不需要手动修改SDS的空间大小,也不会出现缓冲区溢出

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

C字符串每次要增加或者缩短一个C字符串,总要对这个C字符串的数组进行一个内存重分配操作:

  • 如果程序执行的增长字符串的操作,执行操作之前,需要通过内存重分配来扩展底层数组的空间大小,如果忘了这一步就会产生缓冲区溢出。
  • 如果程序执行的是缩短字符串的操作,执行操作之后,需要通过内存重新分配来释放字符串不再使用的那部分空间,如果忘了这一步就会产生内存泄漏。

注:内存重分配涉及复杂的算法,并且可能需要执行系统调用,是一个比较耗时的操作。

SDS通过未使用空间,实现了空间预分配惰性空间释放两种优化策略

空间预分配

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

  • 修改之后,SDS的长度(len属性的值)小于1MB,那么分配和len属性同样大小的未使用空间。
  • 修改之后,SDS的长度大于等于1MB,程序会分配1MB未使用空间
惰性空间释放

惰性空间释放用于优化SDS的字符串缩短操作:当SDS的API需要缩短SDS保存的字符串,程序不会立即使用内存重分配来回收多出来的字节,而是使用free属性将这些字节的数量记录起来,并等将来使用。惰性空间释放策略不仅避免了缩短字符串时所需的内存重分配操作,还为将来可能的增长操作提供了优化。

二进制安全

SDS API都是二进制安全的,所有SDS API都会以处理二进制的方式来处理SDS存放的buf数组里的额数据,程序不会对其中的数据做任何限制、过滤、或者假设,数据在写入时是什么样的,它被读取时就是什么样的

兼容部分C字符串的函数

总结:

redis只会使用C字符串作为字面量,在大多数情况下,redis使用SDS作为字符串的表示。
相比C字符串,SDS优点:

  1. 常数复杂度获去字符串长度
  2. 杜绝缓冲区溢出
  3. 减少修改字符串长度时所需的内存重分配次数
  4. 二进制安全
  5. 兼容部分C字符串函数

热门文章

暂无图片
编程学习 ·

二、21【设计模式】之状态模式

今天的博客主题设计模式 ——》 设计模式之状态模式状态模式 SP (State Pattern)定义允许对象在内部状态发生改变时改变它的行为,看起来好像修改了它的类。类的行为是由状态决定的,不同的状态下该类有不同的行为。就是一个对象在其内部改变的时候,它的行为也随之改变。核心…
暂无图片
编程学习 ·

ubuntu:beyond compare 4 This license key has been revoked 解决办法

错误如图所示:解决办法:(1)先用find命令找到bcompare所在位置:sudo find /home/ -name *bcompare(2)进入 /home/whf/.config,删除/bcomapre文件夹注意一般.config为隐藏文件,通过 ctrl+h 可以显示:(3)cd /usr/lib/beyondcompare/ (4)sudo sed -i "s/keexjEP3…
暂无图片
编程学习 ·

RFID资产管理解决方案-RFID固定资产管理-新导智能

RFID资产管理解决方案系统集成了技能含量很高的远间隔无线射频辨认技能、短间隔射频技能及多用户防抵触技能监测技能,标签、定位器、读写器、通讯网关等,选用全新的嵌入式微处理器和嵌入式软件进行规划,体系信号穿透力强,对人体无电磁污染、环境适应性强,可一起定位多个标…
暂无图片
编程学习 ·

元注解

元注解 元注解时定义注解的注解,是Java提供的用于定义注解的基本注解注解 说明@Retention 是注解类,实现声明类Class,声明类别Category,声明扩展Extension@Target 放在自定义注解上的上边,表明该注解可以使用的范围@Inherited 允许子类继承父类的注解,在子类中可以获取使…
暂无图片
编程学习 ·

Spring——Bean scope

Spring framework 支持6个范围(scope),其中4个只能在用web-aware时才能使用。当然,你也可以创建自定义范围。singleton : spring默认就是singleton,即在注册该bean的时候,会把这个bean存储到单列bean缓存,以后对该bean的所有的后续请求和引用都会返回缓存中的这一个bean…
暂无图片
编程学习 ·

react组件返回上级时,记录上级组件状态

最近开发项目中,做管理后台,很多表格列表,有搜索条件,有分页;在跳转到详情页面,返回时,列表组件重新渲染,之前的搜索条件,分页什么的,都没有记住;还需要重新选,点击,交互体验很不好。1.这里想到2两个办法,一个是吧搜索条件存到缓存中;每次进行读写;条件太多,或…
暂无图片
编程学习 ·

2.4-1、斐波那契数列

1、斐波那切数列 【问题描述】 斐波那切数列0,1,1,2,3,5,8,13,21,34,55……从第三项起,每一项都是紧挨着的前两项的和。写出计算斐波那切数列的任意一个数据项递归程序。 【输入格式】 输入所求的项数。 【输出格式】 输出数据项的值。 【输入样例】fbi.in 10 【输出…
暂无图片
编程学习 ·

其实AQS并不难

不啰嗦,直接上干货 文章目录上锁解锁总结条件队列 newConditionCLH队列的数据结构扩展 interrupted 上锁ReentrantLock reentrantLock = new ReentrantLock(true);或者ReentrantLock reentrantLock = new ReentrantLock();看构造函数://无参的构造函数,默认为非公平锁public…
暂无图片
编程学习 ·

rem移动端布局

rem移动端布局: 1、rem是CSS3新增的相对长度单位,是指相对于根元素html的font-size计算值的大小。简单可理解为屏幕宽度的百分比。 2、什么是dpr? dpr是屏幕像素密码比 计算:dpr=液晶屏幕px尺寸 / 物理尺寸(量多少就是多少) 常用的dpr有:dpr = 2,dpr=3 window.devicePi…
暂无图片
编程学习 ·

JVM-面试题

一、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译…
暂无图片
编程学习 ·

堪称零瑕疵!仅用了330页直接封神,我要吹爆这份RocketMQ笔记

RocketMQ天生为金融互联网领域而生,追求高可靠、高可用、高并发、低延迟 RocketMQ在阿里集团也被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景 其主要功能有:灵活可扩展性、 海量消息堆积能力、 能够保证严格的消息顺序 提供丰富的消息拉…
暂无图片
编程学习 ·

排序算法之插入排序、希尔排序、归并排序(C#)

插入排序 两次for循环,外层从数组第二位i=1开始,内层for循环由i向前进行判断,大于则将该位置与遍历位置交换。此时注意,不能按i的位置获取元素,应将该元素暂存,因为交换时对应i位置元素值会变换。c#代码如下/// <summary>/// 插入排序/// </summary>/// <…
暂无图片
编程学习 ·

1.9 OSPF 特殊区域

笔记用由typora写的,我截图效果好一点,笔记复制过来有很多地问题(图片不显示,排版问题等等)。
暂无图片
编程学习 ·

用Tableau制作滚动时间轴(下)

上一篇文章《用Tableau制作滚动时间轴(上)》我们介绍了滚动时间轴的基本制作方法。这篇文章我们继续丰富和美化时间轴。制作内容显示工作表由于数据集内有大量的文字描述内容,那么让这些内容显示到时间轴里,就不太现实了。需要单独建立一个工作表来显示文字内容。这里我们还…
暂无图片
编程学习 ·

Java调起手机电脑摄像头

一、直接上代码 要导入的maven<!-- java调用摄像头 --><!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform --><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><vers…