第2章 简单动态字符串

2017-05-16 17:39:13.0

    Redis没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用作Redis的默认字符串表示。

    在Redis里面,C字符串只会作为字符串字面量(string literal)用在一些无须对字符串值进行修改的地方,比如打印日志。

    当Redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,Redis就会使用SDS来表示字符串值,比如Redis的数据库里面,包含字符串值的键值对在底层都是由SDS来实现的。

2.1 SDS的定义

    每个sds.h/sdshdr结构表示一个SDS值:

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

    关于SDS:

  1. free属性的值为0,表示这个SDS没有分配任何未使用空间。
  2. len属性的值为5,表示这个SDS保存了一个五字节长的字符串。
  3. buf属性是一个char类型的数组。

     SDS遵循C字符串以空字符结尾的惯例,保存空字符串的1字节空间不计算在SDS的len属性里面,并且为字符串分配额外的1字节空间,以及添加空字符到字符串末尾等操作,都是由SDS函数自动完成的,所以这个空字符串对于SDS的使用者来说是完全透明的。遵循空字符结尾的好处是:SDS可以直接重用一部分C字符串函数库里面的函数 。

2.2 SDS与C字符串的区别


C字符串SDS
获取字符串长度的复杂度为O(N)获取字符串长度的复杂度为O(1)
API是不安全的,可能会造成缓冲区溢出API是安全的,不会造成缓存区溢出
修改字符串长度N次必然需要缓冲区N次内存重分配修改字符串长度N次最多需要执行N次内存重分配
只能保存文本数据可以保存文本或二进制数据
可以使用<string.h>为中的函数可以使用一部分<string.h>库中的函数

2.4 重点回顾

Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple Dynamic String,简单动态字符串)作为字符串表示。

比起C字符串,SDS具有以下优点:

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

· 杜绝缓冲区溢出

· 减少修改字符串长度时所需的内存重分配次数

· 二进制安全

· 兼容部分C字符串函数






下一篇:第3章 链表 19