简单动态字符串

简单动态字符串

Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串),而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型, 并将 SDS 用作 Redis 的默认字符串表示。内部结构实现上类似于 Java 的 ArrayList。

SDS 的结构是一个带长度信息的字节数组:

struct SDS<T> {
  int free; // buf 剩余可用长度
  int len; // buf 已占用长度
  char buf[]; // 实际保存字符串数据的地方
}
ℹ️
对 buf 分配一些额外的空间,并使用 free 记录未使用空间的大小。Redis 字符串是可以修改的,它支持 append 操作。如果数组没有冗余空间,那么追加操作必然涉及到分配新数组,然后将旧内容复制过来,再 append 新内容。如果字符串的长度非常长,这样的内存分配和复制开销就会非常大。这是利用空间换时间的策略。

使用 SDS 的原因:

  • 二进制安全。C 字符串是以 \0 字符为结尾的,如果客户端传过来的字符串包含 \0 字符,那么服务器在处理这个字符串时,会将 \0 后的字符串舍弃掉。适配不同语言的客户端。
  • 兼容部分 C 字符串函数。SDS 结构体中的 content 中的字符串是以字节 \0 结尾的字符串,之所以多出这样一个字节,是为了便于直接使用 glibc 的字符串处理函数。

扩容策略

字符串在长度小于 1M 之前,扩容空间采用加倍策略,也就是保留 100% 的冗余空间。当长度超过 1M 之后,为了避免加倍后的冗余空间过大而导致浪费,每次扩容只会多分配 1M 大小的冗余空间。

Redis 的 key

Redis 是一个键值对数据库,key 是字符串,value 是字符串、列表、哈希、集合、有序集合。

虽然 Redis 可以使用非字符串类型作为 key,例如:

redis> set 100 100
OK
redis> get 100
"100"
redis> set 0.1 200
OK
redis> get 0.1
"200"

虽然看起来是数字或者浮点数,但是 Redis 会将其作为字符串来处理。

最后更新于