redis数据结构(二)字符串类型底层的数据结构

2022/3/29 2:52:39

本文主要是介绍redis数据结构(二)字符串类型底层的数据结构,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

为什么需要SDS

字符串数据类型作为redis最基础的数据类型之一在redis中使用的也是最频繁的数据类型.

因为redis只有一个线程在执行指令,如果某一个指令执行时间过长其他指令都会排队等候,又因为在c语言中获取字符串长度的时间复杂度为O(n),并且每次在字符串扩容或者缩容的时候,c语言中的字符串都需要重新分配内存,并且复制数组,这个两个操作是redis承受不起的,所以redis弃用了c语言中的字符串类型,自己定义了一种SDS(Simple Dynamic String)的数据结构用来存储字符串类型的数据.

 

SDS的结构

struct SDS<T> {
    T capacity; // 数组容量,包含了字符串的真实长度和预留出来执行append操作的空间
    T len; // 数组长度,当前字符串的真实长度
    byte flags; // 特殊标识位,标识当前的SDS为哪一种头部
    byte[] content; // 数组内容,保存了真正的数据
}          

len字段是为了在获取字符串长度的时候不对字符串进行遍历,所以SDS保存了字符串的长度len.这样在获取字符串长度的时候直接返回len即可.

capacity字段为该条字符串占用的长度字节数.在第一次分配内存的时候redis会为字符串分配len长度的数组,但是在执行一次append操作之后,redis会认为还有可能再次执行append操作,所以会预留出空间来防止每次进行append操作的时候都进行重新分配内容和拷贝字符串,redis默认的预留空间为原来的一倍,但是最大为1M的内存空间.如果字符串操过了1M,redis每次扩容最大也只会预留出1M的空间,防止内存浪费

flags字段是为了区分不同的SDS头部做的一个标识.redis为了节省内存空间,在保存不同长度的字符串的时候capacity和len使用的长度也是不同的,redis为此定义了很多不同的SDS头部.

// flags的低三位代表不同类型的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  //字符串长度使用四个字节标识
#define SDS_TYPE_MASK 7 //为了方便的获取字符串的类型,只需要flags字段和SDD_TYPE_MASK做位与操作就可以得到SDS头部的类型
#define SDS_TYPE_BITS 3 //因为SDS_TYPE_5类型的字符串的值是保存在flags中的,所以只需要flags字段向左移动SDS_TYPE_BITS位就可以得到字符串保存的值

 

embed or raw

在redis中为了减少内存分配的次数,redis把44(闭区间)以下长度的字符串使用embed格式存储,45长度以上的字符串使用raw格式存储,embed和raw格式的唯一区别就是,embed格式的时候字符串的SDS头部和字符串的值是保存在内存的一块连续的存储空间中的,redis只需要分配一次内存就可以,而raw格式中SDS的头部和字符串的内容是分开保存的,这样redis会分配两次空间.

为什么redis是以44个长度为分界点呢?这个需要从redisObject的结构说起.具体redisObject的结构可以查看redis数据结构(一).每个redisObject中都会占用16字节的长度,而SDS结构的大小为len(capacity)+len(len)+len(flags)+len(content),当字符串比较短时capacity和flags和len都只会占用一个字节的长度,所以一个sds占用的空间为16+3+capacity的长度.又因为redis分配内存的时候只会分配2,4,8,16,32,64等等,如果一个redisObject超过了64字节,redis就会认为这是一个大字符串,就会采用raw格式存储.这时使用embed存储的字符串的最大长度为64,减去固定的19个字节串为45个字节,在减去redis中字符串结尾固定的\0字符,所以embed总共可以存储的最大字节数为44

 



这篇关于redis数据结构(二)字符串类型底层的数据结构的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程