Redis 数据类型 String 学习笔记 | 青训营

74 阅读2分钟

底层是 SDS,动态字符串

而 SDS 在 RedisObject 中对应三大物理编码:

  • int
  • embstr
  • raw

int:

如果存储的字符串是整数值,并且大小在 LONG_MAX 范围内,则会采用 INT 编码:直接将数据保存在 RedisObject 的 ptr 指针位置(刚好8字节),不再需要 SDS 了。

像这样

emdstr:

如果存储的 SDS 长度小于44字节,则会采用 EMBSTR 编码,此时 object head 与 SDS 是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。

像这样

为什么是 44 字节,因为 redisObject 占 16 个字节,SDS 前三个字段占 3 个,字符数组结尾的 \0 占一个,所以字符串的长度为44

这样可以组成 64 字节大小的内存片段,因为 redis 做内存分配的时候会议 2^N 去分配,这样不易产生内存碎片

raw:

保存长度大于44字节的字符串

证明

实现

一个 SDS 由四个字段构成,前三个字段各占 1 个字节

  • len:已用的字节长度
  • alloc:字符串的最大字节长度
  • flags:用来表示 SDS 的类型
  • buf[]:真正有效的字符串数据,长度由 alloc 控制

sds.h

有多种大小的 SDS,大部分情况我们使用 8 位都足够了,256 字节以下的长度

字符串扩容机制:

如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;

如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。

为什么 SDS

C 语言靠自己的 char[] 来实现。

为什么:

  • 获取字符串长度的需要通过运算
  • 非二进制安全
  • 不可修改

字符串在 C 语言中的存储方式,想要获取「Redis」的长度,需要从头开始遍历,直到遇到 '\O' 为止。所以,Redis 没有直接使用C语言传统的字符串标识,而是自己构建了一种名为简单动态字符串 SDS(simple dynamic string)的抽象类型,并将 SDS 作为 Redis 的默认字符串。