2021-07-06

什么是SDS简单动态字符串

Redis只有在不需要修改字符串的值还是直接展示字符串值的地方使用C语言字符串(以空字符结尾的字符数组),比如打印日志。在会修改字符串值的地方都是使用SDS简单动态字符串。比如包含字符串值的键值对都是使用的SDS来底层实现的。

除了用来保存数据库中的字符串值以外,SDS还被用做缓冲区(buffer):AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区,都是由SDS实现的。

SDS的定义

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

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

在这里插入图片描述
SDS遵循C字符串以空字符结尾的惯例。遵循这一惯例的好处是,SDS可以直接使用一部分C字符串函数库里面的函数。

SDS与C字符串的区别

  1. 获取字符串长度的区别
    C字符串没有保存字符串的长度,想要获取字符串长度需要从保存字符的buf数组的头部一个个遍历到尾部去计算长度,而SDS的结构里有一个len字段保存了SDS字符串的长度,在插入、更新、删除字符串时,会自动更新维护这个字段。

  2. SDS可以杜绝缓冲区溢出
    SDS的结构里存在一个free字段,这个字段代表的是buf数组里未被分配的空间。而C字符串里是没有未被分配的空间的,所以当C字符串在拼接另外一个字符串的时候,如果没有判断目前C字符串是否分配了足够的空间,当空间不足的时候就会导致缓冲区溢出。
    比如:存在两个字符串A和B,这两个字符串在内存是相连的,当字符串A的内容被修改了,这个时候如果没有先去判断字符串A的长度是否能够容纳新值,同时这个新值也真的超过了字符串A的空间长度,这个时候字符串A修改完后也会将字符串B的值也修改了。

  3. SDS可以减伤修改字符串带来的内存重新分配次数
    C字符串因为并不记录自身的长度,所以每次增长或缩短C字符串,都需要对C字符串的数组进行一次内存重新分配:

    • 如果程序执行的是增长字符串的操作,程序需要先通过内存重新分配来扩展底层的数组大小,不进行这个操作就会导致缓冲区溢出。
    • 如果程序执行的是缩短字符串的操作,程序需要先通过内存重新分配来释放掉底层数组未使用的空间,不进行这个操作就会导致内存泄漏。

    SDS保留了一个free字段,记录buf数组里未被分配的空间。当进行要增长字符串长度的时候,如果未分配空间足够大,那么就可以直接增长字符串长度。当进行要缩短字符串长度的时候,可以直接缩短字符串长度,缩短后留下的空间可以直接划给未分配空间,留待下次增长字符串长度时使用。

    • 当SDS字符串长度未达到1M时,free的大小和SDS字符串长度的大小一致。
    • 当SDS字符串长度大于1M时,free的大小一直为1M。
  4. SDS的buf数组保存的是二进制数据
    C字符串因为需要以空字符串来标识一个字符串的结尾,所以导致C字符串只能保存文本数据,不能保存像图片、视频等二进制数据。但是SDS的结构len字段保存了SDS字符串的长度,不再需要以空字符串来标识字符串的结尾,所以SDS字符串的buf数组保存的是二进制数据,这让Redis能够缓存更多种类的数据。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值