【redis】sds数据结构

本文从源码介绍sds的数据结构。

sds是redis中对传统字符串的封装,在其上加入了长度等信息。用于redis中key等字符串类型数据的存储。

1 sds的数据结构

typedef char *sds;

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

如上代码,sds实际上有五类,具体的类型由flags来确定,其内存形式如下:

【redis】sds数据结构_第1张图片

  • len保存当前数据已占用的字节数;
  • alloc保存数据可用的全部内存空间(实际上数据部分占用的字节数是alloc + 1);
  • alloc - len 是当前可用空间;
  • flags表示sds的类型,该类型决定了 len 和 alloc所占用的大小。
  • 对于sdshdr5, head部分只有一个字节,其中高5位存储的是len,低三位是sdshdr5的类型。
  • sds总是保持数据最后的一个字节是0,同时,提供的sds指针是指向了数据部分其实的位置,所以sds可以直接被用于c的字符串函数。

 

2 sds的操作

主要的操作包括新建、赋值、追加。一般来讲,就是扩容和缩容两个操作,对于扩容,扩容后<1M的字符串,每次扩容都在扩容之后基础上翻倍;>=1M,则每次再多扩1M。大多情况下,被扩容的内存大概率再次被扩容,这样做可以减少扩容次数,从而提高性能。

扩容不会产生  sdshdr5 类型的sds,这是因为 sdshdr5 没有保存 容量,不能额外扩容,只能每次需要的时候都进行扩充。

扩容会改变字符串类型,旧sds不可用,需要使用新的sds。而缩容则不会改变字符串类型。

 

你可能感兴趣的:(redis)