redis学习笔记之数据结构-----SDS(简单动态字符串)

目录

SDS结构

redis字符串存储两种形式(embstr和raw)

SDS和C字符串区别

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

  • SDS结构

struct sdshdr{
    // 1bytes 数组容量
    int8 capacity;

    //1bytes 数组长度
    int8 len;

    //1bytes 特殊标志位
    int8 flags;
    
    //长度取决于实际情况 数组内容
    byte[] content;
};

content除了保存字符串的字符外, 还会在末尾保存一个空字符 '\0' , 空字符不计算在 len 属性之中,遵循空字符结尾的好处是可以重用一部分C字符串的函数

  • redis字符串存储两种形式(embstr和raw)

我们先看下在客户端运行的代码:

127.0.0.1:6379> set test_str 11111111111111111111111111111111111111111111
OK
127.0.0.1:6379> debug object test_str
Value at:0x7f7fb8215100 refcount:1 encoding:embstr serializedlength:12 lru:11329907 lru_seconds_idle:16
127.0.0.1:6379> set test_str 111111111111111111111111111111111111111111111
OK
127.0.0.1:6379> debug object test_str
Value at:0x7f7fb826dc40 refcount:1 encoding:raw serializedlength:12 lru:11329942 lru_seconds_idle:4
127.0.0.1:6379> 

从代码可以发现当字符串长度为44的时候,是以embstr形式存储,大于44的时候则以raw的形式存储,那么为什么以44为分界线呢?

我们简单看下redis对象头部

struct redisObject {

    // 类型  4bits
    int4 type;

    // 编码  4bits
    int4 encoding;

    // lru 24bits
    int24 lru;
   
    // 引用计数 4bytes
    int32 refcount;

    // 8bttes (64位操作系统) 指向底层实现数据结构的指针  
    void *ptr;

} robj;

embstr使用malloc(动态内存分配)分配一次内存,对象头和SDS对象连续存储一起,而raw需要两次,两个对象头不是连续存储在一起。在内存分配器(jemalloc)中,分配内存大小的单位是2/4/8/16/32/64字节等,所以可以看出最长的就是用64字节,64字节减去redis头部(16)和SDS对象(3)还剩下45个,字符串结尾又是以NULL结尾,所以字符串最大长度就是44。

 embstr(embedded string):字符串的空间将会和redisObject对象的空间一起分配,两者在同一个内存块中。采用这个方式可以减少内存分配的次数,提高内存分配的效率,降低内存碎片率。

raw:调用两次内存分配函数来分别创建 redisObject 结构和 sdshdr 结构, 而 embstr 编码则通过调用一次内存分配函数来分配一块连续的空间, 空间中依次包含 redisObject 和 sdshdr 两个结构

注意:value是整型且长度满足long长度,存储类型为int,可以结合我上面操作试试

SDS和C字符串区别

  1. 获取字符串长度的时间复杂度:SDS:O(1) ,C:O(n)
  2. 二进制安全:C 字符串中的字符必须符合某种编码(比如 ASCII),SDS 都会以处理二进制的方式来处理 SDS 存放在 content 数组里的数据(这里要注意写代码时候有时候要注意转码格式,要和redis一致,防止乱码)
  3. 惰性空间释放: 当 SDS  API 需要缩短 SDS 保存的字符串时, 程序并不立即使用内存重分配来回收缩短后多出来的字节
  4. 空间预分配:当字符串小于1MB时候,扩容采用加倍方式,大于1MB则每次给他分配1MB

 

本文来自于redis深度历险,redis设计与实现redis官方文档等待总结出来的,有什么不足请谅解,最后还是大家有空去去读下钱文品的redis深度历险这本书很给力的。

猜你喜欢

转载自blog.csdn.net/lin_keys/article/details/105884549