从源码中分析SDS相较于C字符串的优势

前言

从本篇文章开始会持续更新有关"redis数据结构源码"的分析。[分析的源码是redis7.2.2版本的,有时候会结合之前的版本]。由于能力有限,有些地方可能有些错误,还望指正。
在分析"intset"的源码的发现。在7.2.2版本,数据类型"set"的底层编码多了一种"listpack",但是之前的版本并没有。本着严谨的态度重新查看了源码以及配置文件,并作出相应的修改。主要修改的地方就是各个版本的数据类型和底层编码的对应图以及编码之间的阈值。

Type && Encoding

redis的每种数据结构都被封装在"redisObject"中,先来看一下"redisObject"长什么样子。

struct redisObject {
   
    unsigned type:4;//表示数据结构的类型,占4bits
    unsigned encoding:4;//数据结构底层使用的编码,占4bits
    unsigned lru:LRU_BITS; //用于LRU或者LFU内存淘汰算法,占24bits
    int refcount;//引用计数,占4bytes,引用计数变为0对象被销毁,内存被回收
    void *ptr;//指向具体的数据,占8bytes
};

接下来看一下"type"都有哪些[以下是五种基本的数据结构]

#define OBJ_STRING 0    /* String object. */
#define OBJ_LIST 1      /* List object. */
#define OBJ_SET 2       /* Set object. */
#define OBJ_ZSET 3      /* Sorted set object. */
#define OBJ_HASH 4      /* Hash object. */

接下来看一下数据结构对应的"encoding"
在这里插入图片描述

redis在3.2版本时引入了"quicklist"[也就是linkedlist+ziplist]
在这里插入图片描述

在这里插入图片描述
redis在5.0版本引入"listpack"

  • 虽然5.0版本引入了"listpack"解决了"ziplist"级联更新的问题,但是hash和zset结构使用的仍然是ziplist。listpack目前只使用在新增加的Stream数据结构中。

在这里插入图片描述

redis在7版本将"ziplist"替换为"listpack"
在这里插入图片描述

在这里插入图片描述

接下来分析"sds"的源码

sds

首先看一下sds的结构
redis-7.2.2\src\sds.h

typedef char * sds;//sds的本质就是char*指向一块连续的内存

sds分为“sdshdr5”、“sdshdr8”、“sdshdr16”、“sdshdr32”、“sdshdr64”五种结构。其中"sdshdr5"从未使用过。

/* Note: sdshdr5 is never used, we just access the flags byte directly.However is here to document the layout of type 5 SDS strings. */
//sdshdr5从未被使用过,只是用它来直接访问flags字节
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; //1byte
    uint8_t alloc;//1byte,不包括头部和终止符
    unsigned char flags; /* 3 lsb of type, 5 unused bits  1byte*/
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
   
    uint16_t len; /* used  2byte*/
    uint16_t alloc; /* excluding the header and null terminator  2byte*/
    unsigned char flags; /* 3 lsb of type, 5 unused bits  1byte*/
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
   
    uint32_t len; /* used  4byte*/
    uint32_t alloc; /* excluding the header and null terminator  4byte*/
    unsigned char flags; /* 3 lsb of type, 5 unused bits  1byte*/
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
   
    uint64_t len; /* used  8byte*/
    uint64_t alloc; /* excluding the header and null terminator  8byte*/
    unsigned char flags; /* 3 lsb of type, 5 unused bits  1byte*/
    char buf[];
};

以上几种结构的布局很相似都是包含"len\alloc\flags\buf"不同的是记录“len\alloc”的字节数不相同。
其中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

encoding

sds底层有三种编码方式
redis-7.2.2\src\server.h

#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */

接下来依次看一下编码方式的选择

createStringObject

[redis-7.2.2\src\object.c]

#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44
robj *createStringObject(const char 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值