Redis数据结构之String原理

一、基本原理redis

Redis 的字符串是动态字符串,是能够修改的字符串,内部结构实现上相似于 Java 的 ArrayList,采用预分配冗余空间的方式来减小内存的频繁分配,如图中所示,内部为当前字符串实际分配的空间 capacity 通常要高于实际字符串长度 len。当字符串长度小于 1M 时, 扩容都是加倍现有的空间,若是超过 1M,扩容时一次只会多扩 1M 的空间。须要注意的是 字符串最大长度为 512M。api

二、数据结构安全

struct sdshdr {
    // buf 中已占用空间的长度
    int len;
    // buf 中剩余可用空间的长度
    int alloc;
    //前3位为数据类型,后5位暂时没有用到 
    unsigned char flags;
    // 数据空间
    char buf[];
};

三、SDS 与C字符串的对比 和优势数据结构

a  O(1) 获取字符串长度函数

由于sds已经存了数据的长度,因此获取字符串长度复杂度为O(1),而C字符串获取长度为O(n)。优化

b  杜绝缓冲区溢出致使的内存问题编码

假设内存区域有s1:“hi”,s2: “redis” 两个字符串,位置紧邻,以下图: 紧邻字符串被覆盖 此时须要给s1 追加一个“boy”, 若是是C字符串,忘记了在追加以前先给s1 分配空间,此时追加将致使 s2的值被意外的修改。 而使用 sds则不会有这个问题。 由于其封装好的函数,会在追加数据以前先检查 空间是否够用,若是不够用就扩容。code

c  经过空间预分配和空间惰性释放图片

减小内存分配问题 当给sds的值追加一个字符串,而当前的剩余空间不够时,就会触发sds的扩容机制。扩容采用了空间预分配的优化策略,即分配空间的时候:若是sds 值大小< 1M ,则增长一倍; 反之若是>1M , 则当前空间加1M做为新的空间。 当sds的字符窜缩短了,sds的buf内会多出来一些空间,这个空间并不会立刻被回收,而是暂时留着以防再用的时候进行多余的内存分配。这个是惰性空间释放的策略内存

d 二进制安全

c字符串必须符合某种编码(例如ASCII),且不能包含空字符。 这些限制使得 c字符窜不能保存图片,音频等二进制文件。 而sds的api 都是二进制安全的,其全部api 都会以处理二进制的方式来处理buf内的数据,因此不会有任何的限制。

相关文章
相关标签/搜索