Redis没有直接使用C语言传统里面的字符串表示(以空字符结尾的字符数组,以下简称C字符串),而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用作redis的默认字符串表示。
而C字符串只会作为字符串字面量(string literal)用在一些无须对字符串值进行修改的地方,比如打印的日志
而当Redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,Redis就会使用SDS来便是字符串值,比如键值对的键和值,AOF缓冲区等都是由SDS实现的。
2.1 SDS的定义

2.2 SDS与C字符串的区别
C字符串是用N+1长度的字符数组来表示长度为N的字符串,并且字符数组的最后一个元素总是空字符串‘\0’。
这个并不能满足Redis对字符串安全、效率以及功能方面的要求
2.2.1 常数复杂度获取字符串长度
C字符串获取长度为O(N),但是SDS中用len记录了字符串长度,所以获取SDS字符串长度总是O(1)
2.2.2 杜绝缓冲区溢出
C字符串不记录自身长度,还有一个问题就是容易造成缓冲区溢出(buffer overflow),如下图

而SDS在拼接之前会先根据free判断是否需要扩充空间再进行拼接
2.2.3 减少修改字符串时带来的内存重分配次数
C字符串无论是增长或者缩短,都需要进行内存重分配,一般程序中,如果修改字符串长度不常出现,那么每次修改都执行一次内存重分配是可以接受的。
不过Redis做为数据库经常被用于速度要求严苛,频繁被修改的场合。
而SDS是存在未使用空间的,通过未使用空间,SDS实现了空间预分配和惰性空间释放两种优化策略。
1、空间预分配
用于优化空间增长操作。
- 如果修改后SDS字符串长度小于1MB,那么程序将分配和len属性同样大小的未使用空间
- 如果改后SDS长度将大于等于1MB,那么将分配1MB的未使用空间
2、惰性空间释放
用于优化空间缩短操作。
一般缩短时,将会将空闲空间作为未使用空间保留,而非内存重分配,当然也有相应的API,在需要时真正的释放SDS的未使用空间。
2.2.4 二进制安全
所有SDS API 会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、或者假设。
2.2.5 兼容部分C字符串函数
遵循C字符串以空字符结尾的惯例,可以保证兼容一些C函数,避免了不必要的代码重复

2.3 SDS API


2.4 重点回顾

网友评论