数据库
首页 > 数据库> > redis字符串源码分析sds

redis字符串源码分析sds

作者:互联网

前言

分析的为redis现在的最新版 6.2.3

源码链接:

sds.h: https://github.com/redis/redis/blob/unstable/src/sds.h

sds.c: https://github.com/redis/redis/blob/unstable/src/sds.c

sds结构体的定义

// 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; // 字符串长度,buf已经用过的长度
    uint8_t alloc; // 字符串的总容量
    unsigned char flags; // 第三位保存类型标志
    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的类型定义:

typedef char *sds;

所以这里为什么sds竟然等同于 char*?sds和传统的c语言字符串保持类型兼容,因此他们的定义是一样的,都是char*。这有些情况下,需要传入一个C语言字符串的地方,也确实可以传入一个sds。但是,sds和 char * 并不等同。sds是Binary Safe的,它可以存储任意二进制数据,不像C语言字符串那样以字符\0来标识字符串的结束,因此它必然有个长度字段。但是这个字段在哪?实际上还有一个header结构:

sds结构体从4.0开始就使用了5种header定义,节省内存的使用,但是不会用到sdshdr5。之所以有五种类型,就是为了节省内存:

一个sds字符串的完整结构,由在内存地址上前后相邻的两部分组成:

#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内部结构解析

sds的数据结构,我们非常有必要非常仔细的去解析它

在这里插入图片描述

上图是一个内部的结构例子,画的很丑

标签:usable,SDS,sds,redis,len,char,源码,TYPE
来源: https://blog.csdn.net/honey_qin/article/details/116402356