redis 简单动态字符串(SDS)

1 简单字符串

redis 自己构建了一种名为简单动态字符串sds的抽象类型,并将sds用作redis的默认字符串类型。

set msg "hello"
  • 键值对的键是字符串对象,实现是保存字符串“msg”的sds
  • 键值的值是字符串对象,是保存字符串“hello”的msg

SDS的定义

struct sdshdr{
    //记录已使用的字节的数量
    int len;
    // 记录数组中未使用的字节数量
    int free;
    //字节数组,用于保存字符串
    char buf[]; 
}

2 sds与c字符串的区别

2.1 常数复杂度获取字符串长度

由于c字符串并不记录自身的长度信息,所以获取c字符串长度信息,需要进行遍历 复杂度为o(N),而sds在len属性中记录了sds长度本身,所以获取仅为o(1)

2.2 杜绝缓冲区溢出

c字符串未分配足够的空间时,数据进行修改时将会发生溢出,而sds进行修改时,将会检查 free属性的大小(代表剩余空间),不足的化将会额外申请。

2.3 减少内存重分配现象

在sds中,buf数组的长度不一定是字符数量加一,数组里面可以包含未使用的字节,而这些字节数量由sds的free属性记录,通过未使用空间sds实现了空间预分配与惰性空间释放两种优化策略。

空间预分配

空间预分配用于优化sds的字符串增长操作,当需要对sds进行空间扩展时,程序不仅仅会为sds分配修改所必须要的空间,还会为sds分配额外未使用空间。

  • 如果对sds进行修改后,sds长度(属性len)小于1MB,那么程序分配和len属性同样大小的未使用空间,这时SDS的len属性值将和free属性值相同。

  • 如果进行修改后,SDS长度大于等于1MB,那么程序会分配1MB未使用空间。

    通过空间预分配,redis可以减少连续执行字符串增长操作所需的内存重分配

惰性空间释放

惰性空间释放用于优化sds字符串缩短操作,当sds需要缩短字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用 free 属性,将这些字节的数量记录起来。

2.4 二进制安全

c字符串中的字符必须符合某种编码(ASCII),不能保存图片,音频等这样的二进制数据在读取时必须按照格式进行读取。

SDS的API都是二进制安全的,所有SDS都会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制。

2.5 总结

sds具有以下优点:

  • 常数复杂度获取字符串长度
  • 杜绝缓冲区溢出
  • 减少修改字符串长度时所需要的内存重分配次数
  • 二进制安全
  • 兼容部分c字符串函数

你可能感兴趣的:(redis设计与实现,redis,数据库)