第2章 简单动态字符串

本文深入探讨了Redis中的简单动态字符串(SDS)结构,介绍了其定义、与C字符串的区别以及提供的API等核心内容,揭示了SDS如何高效地处理字符串操作。

在Redis里面,C字符串只会作为字符串字面量,用在一些无须对字符串值进行修改的地方。

在Redis数据库里面,包含字符串值的键值对在底层都是由SDS实现的。

除了用来保存数据库中的字符串值之外,SDS还被用作缓冲区:AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区。


1. SDS 的定义

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

// sdshdr 结构
struct sdshdr {

    // buf 已占用长度
    int len;

    // buf 剩余可用长度
    int free;

    // 实际保存字符串数据的地方
    // 利用c99(C99 specification 6.7.2.1.16)中引入的 flexible array member,通过buf来引用sdshdr后面的地址,
    // 详情google "flexible array member"
    char buf[];
};

SDS遵循C字符串以空字符串结尾的惯例(可以直接重用一部分C字符串函数库里面的函数),保存空字符的1字节空间不计算在SDS的len属性里面,由SDS函数自动完成空字符空间分配,以及空字符添加到字符串末尾。

对于SDS使用者完全透明。


2. SDS与C字符串的区别

C语言使用长度N+1的字符数组表示长度为N的字符串,并且最后一个元素总是空字符‘\0’

2.1 常数复杂度获取字符串长度

O(1)

设置和更新SDS长度的工作是由SDS的API在执行时自动完成的。


2.2 杜绝缓冲区溢出

SDS的API会先检查SDS的空间是否满足修改所需的要求,不满足,API会自动将SDS的空间扩展至执行修改所需的大小


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

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

1.空间预分配


额外分配未使用空间数量由以下公式决定(空间不够时)

  • 如果对SDS进行修改之后,SDS的长度(即len属性)小于1MB,那么程序分配和len属性同样大小的未使用空间,这时SDS len属性值将和free属性相同。
  • 如果对SDS进行修改之后,SDS的长度将大于等于1MB,那么程序会分配1MB的未使用空间。

2.惰性空间释放

SDS的API需要缩短SDS保存的字符串时,使用free属性将这些字节的数量记录起来。


2.4 二进制安全

‘\0’

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


2.5 兼容部分C字符串函数


3.SDS API

sdsnew

sdsempty

sdsfree

sdslen

sdsavail

sdsdup 创建一个给定SDS的副本

sdsclear  

sdscat

sdscatsds

sdscpy

sdsgrowzero 用空字符将SDS扩展至给定长度

sdsrange 保留SDS给定区间内的数据,不在区间内的数据会被覆盖或清除

sdstrim 接受一个SDS和一个C字符串作为参数,从SDS中移除所有在C字符串中出现过的字符。

sdscmp 对比两个SDS字符串是否相同个



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值