[redis读书笔记] 第一部分 数据结构与对象 简单动态字符串

本读书笔记主要来自于<<redis设计与实现>> -- 黄键宏(huangz)

redis主要设计了字符串,链表,字典,跳跃表,整数集合,压缩列表来做为基本的数据结构,实现键值对(key-value)中的值(value),键的数据类型主要是字符串。

1. 简单动态字符串:

 redis没有使用C的字符串,而是自己定义了数据结构来实现字符串,主要实现在sds.h和sds.c里,主要结构是下面的sdshdr。

struct sdshdr {
    
    // buf 中已占用空间的长度
    int len;

    // buf 中剩余可用空间的长度
    int free;

    // 数据空间
    char buf[];
};

     sds字符串实现的优点:

    - 传统C语言的字符串长度获取的复杂度为o(N), 用sdshdr.len可以将复杂度降为o(1)

    - 因为C语言的字符串不自带长度信息,进行字符串的扩充/拷贝操作时,容易产生溢出,而sds的实现,因为有len和free两个变量来记录空间信息,那么在比如sdscat(类似strcat)的实现里,会先判断sdshdr.free是否足够给新的字符串,如果不够,会先申请新的空间(sdsMakeRoomFor()),这样保证了不会有溢出

    - C语言的字符串操作,如果要做扩充/截断操作,是需要重新分配/扩展/释放内存,再进行老的字符串到新字符串的内存迁移操作,对于redis这样对速度要求高的数据库,频繁的内存分配/释放操作对性能有影响,所以通过利用sdshdr.len和sdshdr.free,可以进行优化,具体为空间预分配和惰性空间释放两个优化策略:

         a.空间预分配:实现在sdsMakeRoomFor(),当用这个函数给某个sdshdr分配新的空间时,它不仅分配需要的空间,还会多分配额外空间,具体为: 1.如果字符串操作结束后,新的sdshdr.len小于1MB,那么sdshdr.free也分配同样大小的长度;2.如果字符串操作结束后,新的sdshdr.len大于1MB,那么分配1MB的free空间,具体举例和sdsMakeRoomFor()中相关实现如下:

        b.惰性空间释放:当SDS的字符串缩短时,空出来的内存不进行释放,而是计入sdshdr.free里,等待将来使用

     - 二进制安全:依赖于sdshdr.len,我们可以用SDS的buf保存各种二进制数据,比如图片,音频等,

   

    - 兼容部分C的字符串函数: SDSHDR的buf里其实存的就是字符串,然后通过len和free进行方便的控制,而SDS里存的内容还是遵循以空字符结尾的C语言管理,所以对sdshdr.buf,可以用C的字符串函数进行调用。

 总结:

原文地址:https://www.cnblogs.com/jiangz222/p/6419661.html