zoukankan      html  css  js  c++  java
  • 《Redis设计与实现》之第二章:简单字符串SDS

    一,什么是SDS?

    1.引出SDS
    C字符串:c语言中,用空字符结尾的字符数组表示字符串
    简单动态字符串(SDS):Redis中,用SDS来表示字符串。在Redis中,包含字符串值的键值对在底层都是由SDS实现的
    首先,Redis使用C语言写的,但是Redis没有使用C语言传统的字符串表示,它自己构建了简单字符串的抽象类型来表示字符串。

    2.SDS的定义
    一个sdshdr结构表示一个SDS值。结构如下:
    struct sdshdr {
        //记录buf数组中已使用字节的数量
        int len;
        
        //记录buf数组中未使用字节的数量
        int free;

        //char类型的数组,用来保存字符串
        char buf[];    
    }
    注意:SDS还是遵循了C字符串以空字符结尾的惯例,最后一个字节保存空字符''。这样做的好处是SDS可以重用一些C字符串函数库里面的函数。

    3.SDS和C字符串的区别
    A.结构上

        

    B.获取字符串的长度时:
        C字符串需要遍历整个字符串,当发现空字符时,停止计数。时间复杂度为O(n)。
        SDS中的len属性记录了SDS的长度。时间复杂度为O(1)。
    C.杜绝缓冲区溢出:
    由于C字符串不记录自身的长度。当修改字符串之前,如果没有为字符串分配(我们手动分配)足够的空间,会造成缓冲区溢出
    当修改SDS字符串时,API会先检查SDS的空间是否满足修改所需要的要求(通过 len free 来判断)。如果不满足,API会自动(不需要我们手动分配)修改SDS空间的大小

    D.减少内存重新分配次数
    对于C字符串来说,每次修改时,都需要对保存这个C字符串的数组进行一次内存重新分配操作。
        如果拼接字符串,在拼接之前,程序需要先通过内存重新分配扩展底层数组的空间大小。否则会缓冲区溢出
        如果缩短字符串,在截断字符串之后,程序需要通过内存重新分配来释放不用的空间。否则会内存泄漏
    对于SDS来说,通过未使用空间 len free,实现了空间预分配和惰性空间释放两种优化策略。
        空间预分配(字符串增长):修改之后,如果SDS的长度小于1MB,程序分配和len同样大小的未使用(len free)
                    空间。如果大于1MB的空间,程序分配1MB的未使用空间。
        惰性空间释放(字符串缩短):缩短字符串后,程序不是立即使用内存重新分配来回收缩短后多出来的字节,
                    而是使用free属性将这些字节的数量记录起来,等待将来使用。

    E.二进制安全

    只关心二进制化的字符串,不关心具体格式,只会严格按照二进制的数据存取,不会根据某种特殊的标志来解析。
    C字符串中,空字符串被当做字符串的结尾来解析的。比如存hello world字符串时,C字符串只会保存hello。因为对于中间的空格,C字符串解析成空字符,当做这个字符串的结尾。world就丢失了。但是SDS字符串,写入是什么样,它被读取就是什么样。那么SDS是如何判断字符串是否结束呢?通过len属性的值获取字符串的长度,字符串长度是多少,在读取字符串的时候就读取多少长度。

    F.兼容部分C字符串函数
    通过遵循C字符串以空字符结尾的惯例,SDS可以在有需要的时候重用<String.h>函数库

  • 相关阅读:
    【NOIP2003提高组】加分二叉树
    【luogu1220】关路灯
    【luogu2583】地铁间谍
    Hello, World!
    python中的画笔控制函数
    python中库引用与import
    python中RGB色彩
    turtle角度坐标体系
    turtle空间坐标系
    python中turtle库的使用
  • 原文地址:https://www.cnblogs.com/inspred/p/10658296.html
Copyright © 2011-2022 走看看