redis五种基本类型剖析(未完...)

概述

redis数据库里的每个键值对都是由对象组成的,其中

数据库的键总是一个字符串对象;

数据库的值可以是字符串对象,链表对象,哈希对象,集合对象,有序集合对象这五种对象中的其中一种。

字符串

redis自己构建了一种名为简单动态字符串(SDS)的抽象类型作为默认字符串表示。SDS的结构在源码中的定义为:

1
2
3
4
5
6
7
8
9
10
struct sdshdr{
//记录buf数组中已经使用字节的数量,等于SDS所保存字符串的长度
int len;

//记录buf数组中未使用字节的数量
int free;

//字节数组,用于保存字符串
char buf[];
}

sds示例

比如一个SDS如图。那如果想改变buf中的内容,比如增加,或者删除会发生什么?

redis的做法为:

增加:先比较要增加的字符长度和目前SDS的free中的空闲字节数,如果free大,则直接插入,修改’\0’的位置和更新free大小。否则,重新分配空间,使得新空间中的free和len均为新字符串的长度。

举个例子,还是上图,如果我在旧的buf中进行了字符串的拼接操作,拼接一个“redis”,原free为0,需要重新分配空间,使得新空间中已使用的字节数为5+5+1=11。len值为10(1是\0),free的值也是10,。也就是说重新分配的空间大小为10+10+1 = 21。其中已使用11字节(有效字符长度10字节),未使用10字节。

redis额外分配的未使用空间数量的规则为:

  • 如果对SDS进行修改后,SDS的长度(len)小于1MB,那么程序分配和len属性同样大小的未使用空间(free),这时SDS的len属性的值和free属性的值相同。

  • 如果SDS修改之后其长度大于等于1MB,那么程序会分配1MB的未使用空间。

这样做的目的就是为了减少连续执行字符串增长操作所需的内存重新分配次数。

删除

当需要缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,以备将来使用。