建议先关注、点赞、收藏后再阅读。
SDS(Simple Dynamic String)是Redis中用于处理字符串的数据结构。
它的内部结构由头部和数据部分组成。
SDS的头部结构如下:
struct sdshdr {
unsigned int len; // 字符串的长度
unsigned int free; // 剩余可用空间的长度
char buf[]; // 实际存储字符串的内存空间
};
SDS的头部包含了三个字段:
len
:表示字符串的长度。这里的长度是指实际存储的字符数量,不包括空字符\0
。通过这个字段可以直接获取字符串的长度,而无需遍历整个字符串。free
:表示可用空间的长度,即当前头部之后的内存空间还有多少字节可用。这个字段的作用是为了避免频繁扩容,当需要对字符串进行修改时,如果空间足够,就直接在后面进行插入或追加操作,不需要重新分配内存。buf
:是实际存储字符串的内存空间。注意,这里的buf
是一个柔性数组(Flexible array member),没有指定长度,实际长度由len
和free
字段决定。
数据部分则是存储实际字符串内容的内存区域,长度为len
字段的值。在这个内存区域里面,通过\0
字符来标识字符串的结尾。
整体上,SDS的内存布局如下所示:
+--------------------+
| SDS 头部 |
+--------------------+
| 数据部分 |
+--------------------+
SDS的头部长度固定为16个字节,不论实际字符串的长度如何,所以对于小字符串的存储开销较大,而对于较大的字符串则相对较小。这是Redis为了追求性能与灵活性做出的设计选择。
SDS通过保存字符串的长度和内容来实现动态分配内存,它的长度和空间预分配策略如下:
-
长度:
SDS内部维护了字符串的长度信息,因此可以以O(1)时间复杂度获取字符串的长度,而不需要每次都遍历整个字符串来计算长度。 -
空间预分配策略:
SDS在分配内存时会预先分配比实际字符串长度更多的空间,这样可以防止字符串频繁地进行内存重分配操作。SDS的空间预分配策略如下:-
如果字符串长度小于1MB,SDS会分配与字符串长度相等的空间,并额外分配1字节的空闲空间,用于保存字符串结尾的’\0’字符。
-
如果字符串长度大于等于1MB,SDS会额外分配1MB的空间,以避免频繁的内存重分配。
-
当字符串长度超出了当前分配的空间时,SDS会按需进行内存重分配,分配大小为字符串长度加上1字节的空闲空间。
-
在内存重分配时,SDS会根据字符串的长度以及当前设置的内存分配策略来决定是否收回多余的空间。
-
SDS的长度和空间预分配策略对Redis的性能有以下影响:
-
获取长度的O(1)时间复杂度:
SDS通过保存长度信息,使得获取字符串长度的操作变得非常高效,不需要每次都遍历整个字符串,对Redis的性能有正面的影响。 -
预分配策略减少内存重分配操作:
SDS的空间预分配策略可以避免频繁地进行内存重分配操作,提高了Redis的性能。 -
减少内存碎片:
SDS的内存重分配操作会根据字符串长度来选择是否收回多余的空间,这样可以减少内存的碎片化情况,提高了Redis的性能。
SDS的长度和空间预分配策略对Redis的性能有正面的影响,通过高效获取长度和减少内存重分配操作,提高了Redis在处理字符串时的性能表现。