背景
redis的字符串,是自定义字符串数据结构,没有使用c语言的字符串数据结构,因为redis的数据经常变动,所以没有使用c的默认数据结构。
redis只有在不需要修改的地方,比如,打印日志的时候,日志里的字符串是c语言字符串。
写读数据的时候,全部都是redis字符串。
redis字符串叫动态字符串。
应用场景
1.日志 c静态字符串
2.key/value redis动态字符串
3.其他
除了用来保存数据库中的字符串值之外,SDS还被用作缓冲区(buffer):AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区,都是由SDS实现的,在之后介绍AOF持久化和客户端状态的时候,我们会看到SDS在这两个模块中的应用。
黄健宏 著. Redis设计与实现 (Chinese Edition) (Kindle 位置 387-389). Kindle 版本.
数据结构
包含3个字段
1.数据
2.已使用长度
3.未使用长度
数据是字符数组。
与c字符串的区别
c语言字符串定义
n个字符 + 结束字符\0(空字符)
区别
1.功能
2.速度
3.安全
C语言使用的这种简单的字符串表示方式,并不能满足Redis对字符串在安全性、效率以及功能方面的要求,本节接下来的内容将详细对比C字符串和SDS之间的区别,并说明SDS比C字符串更适用于Redis的原因。
黄健宏 著. Redis设计与实现 (Chinese Edition) (Kindle 位置 417-418). Kindle 版本.
功能
c字符串只能存储文本,因为c字符串结束的标志是空字符,而redis字符串可以存储二进制数据(例如,图片 视频等),redis结束的标志是已使用长度字段,而不是空字符,虽然redis也有空字符,那是为了兼容已有的c库函数。
注:redis字符数组字段也是字节数组。
速度
获取字符串长度,c是N,redis是1,因为一个没有记录长度,一个有记录长度。没有记录长度,只能遍历,直到碰到结束字符\0。
安全
c字符串不会自动扩充,当内存不够的时候,所以如果内存不够,还要往后面拼接数据,那么就会覆盖别的数据。
redis字符串会自动扩充,拼接字符串的时候,会先判断内存是否足够,不够就扩充,再拼接数据。
具体怎么扩充呢?假设字符串后面有数据,怎么办?是先把后面的数据挪动,然后再扩充内存,最后拼接数据吗?
总结
加数据和减数据
c不管是加数据和减数据,都会内存重分配,加数据,要内存重分配,减数据,也要内存重分配,还要回收减掉的数据。
redis加数据的时候,会自动扩充内存,这是其一。其二,除了会自动扩充已使用内存,同时还会扩充未使用内存,这样下次连续加数据的时候无需多次扩充。具体扩充的计算公式是,1.小数据,已使用和未使用一样 2.大数据,未使用1M。
减数据的时候,不是立马回收减的数据,而是放到未使用内存字段,除非你想要手动回收数据。
内部编码数据结构
1.数字类型
2.短字符串
3.长字符串
数字类型是int(8个字节),短字符串是短str(30个字节),长字符串是长str(30个以上的字节)。
参考
黄健宏 著. Redis设计与实现