《redis设计与实现》学习之SDS

最近在看《redis设计与实现(第二版)》这本书

《redis设计与实现》学习之SDS

此文一方面是对自我学习做一个巩固和记录,另一方面分享给有意提高自己知识面的小伙伴儿

由于鄙人看书一贯都是看着看着都快睡着了的状态,所以看书对我来说其实是一种煎熬,但是我会慢慢适应逐渐改掉这个坏毛病。

刚看没几天,进度很慢。所以内容可能没有之前那么大篇幅和技术广度。

言归正传。

Redis是一个开源的使用ANSI C语言编写的可基于内存亦可持久化的日志型、Key-Value数据库。想必很多开发人员没有没听过的吧?

Redis非常强大它支持存储的value类型很多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中。

Redis的底层定义了一种数据结构动态字符串(simple dynamic string,SDS)来表示字符串值。

比如:执行命令

redis>set msg "hello word"

ok

那么redis将在数据库中创建一个键值对。键和值都是一个字符串对象。也就是说对于键msg,底层保存着一个字符串“msg”的sds,对于值hello world 底层同样保存着字符串“hello world”的sds

再比如:

redis>rpush result "a" "b" "c"

(integer) 3

result键是一个保存了字符串"result"的sds,

其值是一个列表对象,这个对象包含三个字符串对象,这三个对象分别由三个sds实现:第一个sds保存着字符串"a",第二个sds保存"b",第三保存"c"

/** 保存字符串对象的结构*/struct sdshdr {  // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间 char buf[];};

《redis设计与实现》学习之SDS

sds示例

① free属性的值0,该SDS没有空闲的未使用空间。

② len 为5,表示字符串的长度为5

③ buf为字符数组,最后一位为\0标识字符串的结束。

SDS遵循C字符串以空字符结束的惯例,保留空字符的1字节的空间,不计算在SDS的len属性中,并且为空字符分配一个字节的空间,遵循这一惯例使得SDS仍然可以使用部分C语言字符串的一些函数。

sds相比C字符串有更多优势:

时间复杂度低

对于获取字符串长度而言,获取c字符串操作的复杂度为O(N),而sds仅为O(1)。c字符串不记录自身长度,为了获取c字符串长度必须要遍历整个字符串。而sds有其len属性,记录着sds本身的长度,不需要遍历sds,直接取值就好了。

可以杜绝缓冲区溢出

这得益于sds的空间分配策略。sds api需要对sds进行修改时会先检查sds空间是否满足修改所需的要求,如果不满足api会自动拓展sds空间再执行修改操作。


此外sds还有空间预分配和惰性空间释放两种优化策略,只要是减少内存重分配次数。

《redis设计与实现》学习之SDS


分享到:


相關文章: