【Redis】SDS结构

发布于:2025-05-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

1、背景

redis作为高性能的内存数据库,对字符串操作(如键、值的存储)有极高的要求。c语言原生字符串(以\0结尾的字符串数据)有一些缺点:长度计算需要遍历(O(n)时间复杂度)、频繁内存重分配、二进制不安全、无缓冲区管理。为了解决这些问题,redis使用了SDS(Simple Dynamic String),在兼容c字符串的同时,提供了更高效、更安全的能力。

2、SDS底层实现

SDS底层结构体如下:

//redis 5+已弃用
struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};

//存储长度范围:0~255(2的8次方减1)
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[];
};

//存储长度范围:256~65535(2的16次方减1)
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[];
};

//存储长度范围:656536~(2^32-1)
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[];
};

//存储长度范围:大于等于2^32字节
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[];
};

根据存储字符串的大小使用不同的sdshdr结构,其字段含义为:

字段名 含义
len 字符串实际长度(已用字节数)
alloc 分配的总容量(不包括头部和结尾的\0)
flags SDS类型
buf[] 存储实际数据

flags代表的宏定义如下:

#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

SDS的特性如下:

特性 实现原理
O(1)长度获取 直接读取len字段,无需遍历
二进制安全 通过len记录字节数(而非依赖\0),可存储任意二进制数据
内容预分配 扩容时按规则分配额外空间,减少重分配次数
惰性释放 缩容时不立即释放内存,通过alloc字段记录剩余空间,供后续操作复用
兼容c字符串 在buf末尾自动追加\0,可直接传递buf给c函数

网站公告

今日签到

点亮在社区的每一天
去签到