sds的种类
c
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len;
uint16_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len;
uint32_t alloc;
unsigned char flags;
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len;
uint64_t alloc;
unsigned char flags;
char buf[];
};
对应的Type值
C
#define SDS_TYPE_5 0
#define SDS_TYPE_8 1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
解释
- len:buf已保存的字符串字节数,不包含结束标示
- alloc:buf申请的总的字节数,不包含结束标示
- flags:不同SDS的头类型,用来控制SDS的头大小
一个完整的sds的结构
以"redis"为例:

其中,非数据部分称为sds的头,也就是len、alloc、flags被称为头。
为什么sds要定义这么多类型?
在这里,许多朋友可能会说:这还需要问吗?显然是为了节约内存。确实,该设计的目的是为了节约内存,但是其中的节约内存的机制可能有些朋友不太清楚。这个设计背后有着深刻的考量,它通过控制长度(len)和分配空间(alloc)所使用的字节数来实现内存的节约,而不是通过控制缓冲区数组(buf)的长度来实现。这样的设计方案确实需要一定的专业知识来理解。
首先我们需要了解不同类型的变量能表示的最大数以及所占用的内存大小
变量类型 | 能表示的数值范围 | 所占用的字节数 |
---|---|---|
uint5_t | 0-31 | 1字节 |
uint8_t | 0-255 | 1字节 |
uint16_t | 0-65535 | 2字节 |
uint32_t | 2^32-1 | 4字节 |
uint64_t | 2^64-1 | 8字节 |
从表格中可以看出,存储一个长度为0~255个字符的字符串,用sdshdr8即可表示,如果使用sdshdr16,在其他条件完全不变的情况下与sdshdr8相比多浪费两个字节(len多消耗一个字节/alloc多消耗一个字节)的存储空间。不要小看这样的设计,sds被广泛运用在redis系统的底层设计之中。古语云:"不积跬步无以至千里,不积小流无以成江海!" 积少成多,将会节省很多内存。