目的
Redis如今是各个系统几乎都在使用的一种分布式高可用的缓存内存中的数据结构存储系统。能够做为数据库、缓存消息中间件、订阅发布系统等。咱们都知道redis中有string、sets、sorted sets、hash、list类型。可是这些咱们常用的数据结构的底层是怎么实现的。今天先记录一下string的结构。主要是参照Redis设计与实现和一些网上的资料总结的一个学习笔记。redis
C语言字符串和SDS在Redis中的使用
redis是用C语言实现的,因此在redis中的string有一些是直接使用C语言的字符串。可是在redis中还使用了叫作简单动态字符串(simple dynamic string)。redis中的string主要就是使用这两种string。可是何时用哪一种呢?具体咱们来看一下。
C语言string:主要使用在一些无序对字符串进行修改的地方,好比说做为key、打印日志
SDS:SDS是redis中默认字符串表示。几乎用于全部须要使用字符串操做的地方,包括AOF缓冲区等模块。
咱们举一个例子:数据库
redis> set aaa "bbb"
这个时候aaa使用的是C语言字符串,bbb则是使用SDS
RPUSH list "aaa" "bbb" "ccc"
list这个key使用的是C语言字符串,aaa bbb ccc则是使用了3个SDS来保存
SDS定义
SDS的定义其实很简单,一共有3个属性。len、free、buf数组
struct sdshdr{
//记录buf数组中已经使用的数量
//等于整个字符串目前已经使用的长度(不包括结束字符"\0")
int len;
//记录buf数组中未使用的字节数量
int free;
//字节数组,用于保存字符串的地方
char buf[]
}
咱们能够看到相比C语言中的字符串,SDS多了两个属性len和free。但就是这两个简单的属性再加上一些扩容策略就能够是的性能有一个很大的提高。接下来咱们能够看一下SDS的优点点在哪里。缓存
SDS优点点
- 快速获取字符串的长度
在SDS的结构中有一个len的属性,若是要获取字符串长度则直接返属性便可。若是C语言字符串,则须要循环字节数组遇到了"0"计算出整个字符串的长度。很明显能够看到SDS使用的复杂度是O(1)。因此说在redis中获取字符串的长度对性能几乎是没有影响的。
- 杜绝缓冲区溢出
在C语言字符串中,当你添加字符到一个字符串是s1长度时若是忘记在执行前为s1分配足够多的空间,那么s1的数据将溢出到以后的字符串s2中,致使s2被意外的修改。
然而SDS不一样,每次对SDS字符串修改以前都会去判断字符串的容量是否足够。若是不够则会扩充SDS的内存大小。因此彻底避免了这个错误。
- 减小字符串修改带来的内存分配次数
在C语言字符串中,每次对字符串的修改都会影响到内存的分配。若是增加字符串,则会为字符串从新分配一个新的内存空间。若是减小字符串,则会对减小的内存空间作内存回收,不然会引发内存泄漏。
那么SDS是如何减小内存分配的呢? 是经过两点
- 空间的预分配
当SDS的API对一个SDS进行修改,而且须要扩展空间的时候,不只会对SDS分配所须要的空间,还会为SDS分配额外的未使用空间。这个未使用空间的长度则记录在free属性中。这个预分配空间的策略根据SDS的长度决定。
1 当SDS小于1MB的时候。每次扩容长度则跟len相同。举一个例子若是一个SDS扩容为12个字节,那么 SDS函数将会再添加一个12字节的预分配长度。既 len=12 free=12 buf长度则为25字节 (多出来的1个是结束符"0")
2 当SDS大于1MB的时候,每次预分配长度则为1MB。至关于若是这个SDS是10MB,那么每次扩容以后的free的长度回是1MB
- 惰性空间释放
当一个SDS字符串缩短操做时,程序并不会立刻从新收回多余出来的内容,而是用free字段将这些空余的空间记录下来。当下次若是须要往SDS添加字符,则能够再次使用这些空余空间。固然也不是意味着永远不会被回收,SDS有API来释放这些内存空间。
- 二进制安全
开始没有理解什么事二进制安全,网上找了一些资料。简单总结:**二进制安全的意思就是,只关心二进制化的字符串,不关心具体格式,只会严格的按照二进制的数据存取,不会妄图以某种特殊格式解析数据。
C语言字符串的字符必须符合某种编码(好比ASCII)而且不能包含空字符,不然空字符以后的字符将会被忽略。二SDS则都是使用二进制处理,不只能够存放字符串还能够放字节流,好比图片,视频等。由于redis不使用空字符串来判断长度而是用len属性。
总结
由于redis做为一个数据库存储来使,并且redis是一个单线程,一旦一个操做阻塞了以后以后的全部操做都会被影响。因此对性能的要求特别高,因此redis本身构建了这种字符串。 其实SDS结构十分简单,简单的使用了len,free两个字段配合一些策略,就大幅度的提升了性能和减小了内存从新分配的次数。值得咱们学习,能够应用在其余程序设计中。安全