1 学习回顾
Redis源码学习(21),sds学习,sds.h
Redis源码学习(22),sds学习,sds.c(一)
Redis源码学习(23),sds学习,sds.c(二)
2 学习概括
2.1 SDS
typedef char *sds;
struct sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
- SDS 是动态字符串(Simple Dynamic String,SDS)的简称。
- SDS 包含len、free、buf三个属性,分别代表字符串长度、可分配空间、字符数组。
- 源代码中的sds是 char *的别名,也是代表字符数组的指针。
2.2 SDS相关方法
- sdslen 方法,返回sds 的字符串长度。
- sdsavail 方法,返回sds剩余空间。
- sdsnewlen 方法,创建一个新的sds字符串。
- sdsempty 方法,创建一个空的sds字符串。
- sdsnew 方法,调用sdsnewlen,创建一个新的字符串。
- sdsfree 方法,释放sds的内存。
- sdsclear 方法,清空sds字符串内容。
- sdsMakeRoomFor 方法,动态扩容, 为sds增加空闲空间。
- sdsIncrLen 方法,sds增加字符串长度。
- sdscatlen 方法, 在sds尾部拼接另一个字符串。
- sdscat 方法,调用sdscatlen ,拼接另一个字符串。
- sdscatsds方法,调用sdscatlen,拼接另一个字符串。
3 学习总结
- 动态字符串(Simple Dynamic String,SDS)是Redis专门设计的一种字符串数据结构。
- SDS结构包含len、free、buf三个属性,分别代表字符串长度、可分配空间、字符数组。
- SDS通过访问len属性可以快速得到字符串的长度,而不是需要遍历字符串每个字符到结尾。
- SDS通过记录free属性,可以查询当前sds还有多少分配空间,这样可以避免反复分配内存空间。
- sds.h头文件里定义sds的结构体定义,还有sdslen、sdsavail方法,还有一些方法签名。
- sds结构需要增加字符串长度的时候会先调用 sdsMakeRoomFor 方法进行动态扩容。
- 动态扩容有两种选择,一种方法是翻倍,一种加1M空间。
- 一般操作了字符串都会变动 sds 的 len和 free属性,两者一般是一加一减的关系。
- 每次变更sds都会在字符尾部设置结束符。
4 学习感悟
原本我以为很简单字符串,没想到Redis都对字符串做了重新设计,叫做简单动态字符串SDS,在保持原有字符串的基础上又附加了长度和空闲空间两个属性。
长度属性,不仅可以使获取字符串长度时间复杂度变为O(1),还可以配合和空闲空间属性做一些联动计算逻辑,一般增加了长度就要减少空闲空间,减少了长度,就要增加空闲空间。
空闲空间属性,可以用来帮助SDS控制存储空间,节省更改字符串重新分配内存空间的次数,要知道Redis追求高性能,如果反复重新分配内存肯定会影响性能。
说到空闲空间的话,就要说道SDS一个非常重要的扩容机制,每次更改字符串如果字符串长度超过空闲长度的话,就要对进行扩容动作,扩容动作有两种方式,一种是将新的字符串长度翻倍,一种是在新长度上再加1M的空间。
在Redis里的字符串都是用SDS来存储,所以了解这个数据结构,可以方便阅读其他的代码,不至于在处于懵逼的状态。