Redis系列之底层数据结构具体实现(SDS)

795 阅读2分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

说明

大家都知道redis有五种基础数据类型,String、List、Hash、Sorted Set、Set。

但是对它们底层数据结构的具体实现有了解吗?

先看一下五种数据类型对应的数据结构。

数据类型对应表.png

通过上图可以发现,只有String类型由一种数据结构实现,其他四种都是由两种数据结构实现的。

我们首先说一下 String类型的底层实现 简单动态字符串。

简单动态字符串 (SDS)

Redis是使用C语言实现的,C语言也有实现存储字符串的函数,Redis为什么不继续使用C语言提供的功能呢?

C语言使用 char* 定义字符数组,但是对于Redis来说,在使用上有一些问题,不符合Redis的需求。

  • C语言的字符数组中,通过遍历整理字符串来获取字符串的长度,使用‘\0’来表示字符串的结尾,如果字符串中间有‘\0’的话,会导致字符串被截取,因此也不能存储任意二进制数据

  • C语言的字符数组在操作上比较复杂。例如常规操作获取字符串长度,需要遍历整个字符串;追加字符串操作,会把被追加的字符串遍历到结尾处,然后把追加的字符串遍历追加到被追加字符串的结尾处。

Redis因为以上C语言字符数组的问题,String类型由简单动态字符串 (Simple Dynamic String,SDS)实现。

下面是SDS的结构图

SDS数据结构.png

存储数据示例

SDS结构示例.png

SDS里面直接存储了字符串的长度,不需要遍历就可以获取,追加字符串时,直接把字符串放到被追加字符串结尾即可,SDS使Redis的操作效率得到提升。

C语言里面需要修改字符串时,都需要对字符数组的内存重新分配,不然会造成缓冲区溢出或者内存泄漏。

而SDS采用的是空间分配的策略,更改字符串时,需要更多空间,如果字符串小于1M,则再分配原字符串大小的空间;如果字符串大于1M,则在原空间上再分配1M的空间。

另外,如果字符串更改后,小于原空间大小,内存不会立即释放,等待下次使用。

结尾

第一次写文章,纪念一下。

如有问题,欢迎指教。