Redis原理:动态字符串SDS

(课程总结自b站黑马程序员课程)

一、引言

Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。

不过Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题:

①获取字符串长度的需要通过运算

②非二进制安全:指‘/0’字符的读取问题。

③不可修改 Redis构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS。

二、源码分析

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[];
};

#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

以sdshdr8为例进行分析:

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; //已使用字符串字节数,不包括结束标志
    uint8_t alloc; //申请总字节数,不包括结束标志
    unsigned char flags; //SDS头信息
    char buf[];
};

这个的uint8_t len记录的字节长度,8位二进制的最大值为255,也就是可以记录最大255字节数的字符串。c语言中char的占用的字节数为1,也就是sdshdr8可以记录长度为255的字符串。

三、结构分析

例如,一个包含字符串“name”的sds结构如下:

Redis原理:动态字符串SDS_第1张图片

SDS之所以叫做动态字符串,是因为它具备动态扩容的能力,例如一个内容为“hi”的SDS:

Redis原理:动态字符串SDS_第2张图片 

假如我们要给SDS追加一段字符串“,Amy”,这里首先会申请新内存空间:

如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;

如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。

(申请分配内存需要Linux从用户态切换到内核态,这个过程需要运用的资源相当多,内存预分配可以在很大程度上节省资源分配)

四、优点 

①获取字符串长度的时间复杂度为O(1)。

②支持动态扩容。

③减少内存分配次数。

④二进制安全。

你可能感兴趣的:(java,redis,数据库,缓存)