简单动态字符串(SDS)

简单动态字符串

简单动态字符串(simple dynamic string,SDS)

SDS的结构

struct sdshdr {
	// 记录buf数组中已使用字节的数量
	// 等于SDS所保存字符串的长度
	int len;

	// 记录buf数组中未使用字节的数量
	int free;

	// 字节数组,用于保存字符串
	char buf[];
}

'\0':空字符

SDS遵循C字符串以空字符结尾的惯例,
保存空字符的1字节空间不计算在len
好处:SDS可以直接重用一部分C字符串函数库里面的函数。

使用场景

字符串字面量:c字符串
可以被修改的字符串:SDS来表示字符串值

SDS的好处

C语言使用长度N+1的字符数组来表示长度为N的字符串,
并且字符数组的最后一个元素总是空字符'\0'
不能满足Redis对字符串在安全性、效率以及功能方面的要求。

1)常数复杂度获取字符串长度
	SDS在len属性中记录了SDS本身的长度
	设置和更新SDS长度的工作是由SDS的API在执行时自动完成的。

2)杜绝缓冲区溢出
	当SDS API需要对SDS进行修改时,
	1)API会先检查SDS的空间是否满足修改所需的要求,
	2)如果不满足,API会自动将SDS的空间扩展至执行修改所需要的大小
	3)然后才执行实际的修改操作

3)减少修改字符串时带来的内存重分配次数
	SDS通过未使用空间解除了字符串长度和底层数组长度之间的关联:
	在SDS中buf数组的长度不一定就是字符数加一,
	数组里面可以包含未使用的字符,
	而这些字节的数量就由SDS的free属性记录

”空间预分配“和”惰性释放“

空间预分配 
		优化了SDS的字符串增长操作:
		对SDS进行空间扩展的时候,
		不仅会为SDS分配修改所必须要的空间,
		还会分配额外的未使用空间(记录在free里)。

		额外分配的未使用空间数量:
			len < 1MB 
				程序分配和len属性同样大小的未使用的空间
			len >= 1MB 
				程序分配1MB的未使用空间

		好处:可以减少内存重分配次数
惰性空间释放
	优化了SDS的字符串缩短操作

		当需要缩短SDS保存的字符串时,
		不会立即使用内存重分配来回收缩短后多出来的字节,
		而是使用free属性将这些字节的数量记录起来,并等待将来使用。

		好处:避免了缩短字符串时所需的内存重分配操作,
			并对将来可能有的增长操作提供了优化。

		SDS也提供了相应的API(sdsclear),在需要的时候,真正地释放SDS的未使用空间。

二进制安全:
	SDS的API都是二进制安全的,都会以处理二进制的方式来处理SDS存放在buf数组里的数据
	数据在写入时是什么样的,被读出时就是什么样
	buf属性称为字节数组的原因:Redis不是用这个数组来保存字符,而是用它来保存一系列二进制数据。
	SDS使用len属性值而不是空字符来判断字符串是否结束。


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

参考 《Redis设计与实现》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值