理解Redis SDS(简单动态字符串)

Redis中使用SDS(Simple Dynamic String)代替C语言字符串,提供O(1)的长度获取、防止缓冲区溢出、减少内存分配次数等优势。SDS结构包含len和free字段,确保内存管理安全且高效。此外,SDS是二进制安全的,能存储媒体数据。
摘要由CSDN通过智能技术生成

简述

Redis中并没有直接使用C语言的字符串表示(在内存中以“\0”作为字符串的结尾),而是自己新建了一个字符串的结构,该结构就是SDS(Simple Dynamic String,简单动态字符串)。

SDS在Redis中的使用

Redis中设计可变字符串都是用的SDS结构,如Redis底层为键值对结构,所有的键都是字符串类型的,就是SDS结构的对象。当然Redis打印日志时,字符串不需要变化,则是使用的C语言的字符串。

SDS结构

struct sdshdr{
    //buf数组中未使用的字节数量
    int free;

    //buf数组中已经使用的字节数量,不包括“\0”
    int len;

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

假如用SDS来存储字符串“Redis”,那么其结构如下:
在这里插入图片描述
len为5,实际buf数组的长度为6,有一个字节用来存储了“\0”。SDS不需要“\0”来判断字符串是否到结尾,那么为什么还要在buf数组最后用“\0”作为结尾呢?其实主要是Redis还要用到C语言中对字符串的处理函数,以“\0”作为结尾,Redis就可以使用这些函数而不用自己去实现。

SDS与C语言字符串的区别

获取字符串长度时时间复杂度O(1)

在C语言的字符串中,以"\0"作为结尾,在需要求字符串长度的时候,需要遍历数组到“\0”处,时间复杂度为O(N)。而在SDS的结构中,可以直接从len中读取长度,时间复杂度为O(1)。

缓冲区溢出问题

传统C语言字符串在执行诸如字符串相加的函数时,是假设使用者已经进行了内存的分配,有足够的内存可以供操作,假如使用者在执行函数之前没有进行内存处理,就可能出现缓冲区溢出的情况。
如:现在有两个字符串S1,S2,结构如下:
在这里插入图片描述
此时,如果直接给S1加上“ Cluster”,就会发生溢出,结构变为:
在这里插入图片描述
可以看到S2的字符串变为“Cluster”。而SDS结构中free字段,明确规定了buf数组空闲字节的数量,执行操作之前可以计算free是否足够放下新的字符串,如果不够就进行内存分配,这样就可以防止缓冲区溢出。

减少内存分配的次数

传统的C语言字符串,在进行字符串相加操作之前,每一次操作都需要进行内存分配,防止缓冲区溢出。而SDS,如果free空闲字节数量足够,完全可以直接进行操作,不需要进行空间申请。那么SDS是怎么判断应该预留多少free的呢?

空间预分配

假如free中空闲的字节数不足以放下新的字符串,那么SDS也会申请进行内存分配,保证buf足够的空间放下新的字符串。当存储的字符串大小小于1MB时,free会和len一样大,也就是假设新的字符串大小len为13,那么free也为13,buf数组的长度为13 + 13 + 1(\0占一位)。如果新的字符串超过1MB,那么free就为1MB。

惰性释放内存空间

buf存储的字符串进行缩减操作时,内存空间并不会立刻释放,释放出来的字节数目会加到free中。

二进制安全

传统的C语音字符串是无法保存媒体数据的,因为如果数据中有“\0”就会被判断为结尾。使用SDS就可以存储媒体数据。

注:"\0"是 ASCII 码为 0 的字符,对应的字符是(Null),C语言中用来判断字符串的结尾

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值