Redis 字符串 String类型的底层实现是什么?
重要内容
Redis 字符串(String)类型的底层实现基于 简单动态字符串(SDS)并且根据字符串内容及长度动态选择编码方式(int、embstr、raw等),以优化内存和性能
扩展知识
不同编码的选择
int 编码
-
适用场景:当存储的字符串可以表示为一个64位有符号整数时,Redis会采用
int编码来存储这个值 -
实现原理:直接使用一个64位的整数来存储该值,这样可以节省内存,并且在进行数值操作(如
INCR、DECR等)时,不需要进行额外的类型转换,提高了操作效率struct redisObject { unsigned type:4; // 数据类型(字符串、哈希等) unsigned encoding:4; // 编码类型,这里是 int int64_t ptr; // 实际的数据指针,这里直接存储整数值 }; -
示例代码
# 设置一个可以表示为整数的字符串 redis-cli set num 123 # 查看该键的编码方式 redis-cli object encoding num # 输出结果:int
embstr 编码
-
适用场景:当存储的字符串长度较短(Redis 3.2 及以前版本中长度小于等于39字节,Redis 3.2 以后版本中长度小于等于44字节)时,Redis会采用
embstr编码 -
实现原理:
embstr是一种专门为短字符串设计的编码方式,它将 RedisObject 结构和简单动态字符串 SDS 结构连续存储在一块内存中,避免了内存碎片,并且减少了内存分配和释放的次数,提高了内存使用效率struct redisObject { unsigned type:4; // 数据类型 unsigned encoding:4; // 编码类型,这里是 embstr void *ptr; // 指向 sdshdr 结构 }; struct sdshdr { uint32_t len; // 当前字符串长度 uint32_t alloc; // 已分配的内存大小 unsigned char flags; // 编码类型 char buf[]; // 实际字符串数据 }; -
示例代码
# 设置一个短字符串 redis-cli set short_str "hello" # 查看该键的编码方式 redis-cli object encoding short_str # 输出结果:embstr
raw 编码
-
适用场景:当存储的字符串长度较长(超过
embstr编码所允许的最大长度)时,Redis会采用raw编码 -
实现原理:
raw编码使用普通的 SDS 结构来存储字符串,RedisObject 结构和 SDS 结构分别存储在不同的内存块中。虽然raw编码在内存使用效率上不如embstr编码,但它可以存储任意长度的字符串struct redisObject { unsigned type:4; // 数据类型 unsigned encoding:4; // 编码类型,这里是 raw void *ptr; // 指向 sdshdr 结构 }; struct sdshdr { uint32_t len; // 当前字符串长度 uint32_t alloc; // 已分配的内存大小 unsigned char flags; // 编码类型 char buf[]; // 实际字符串数据 }; -
示例代码
# 设置一个长字符串 redis-cli set long_str "abcdefghijklmnopqrstuvwxyz1234567890abcde" # 查看该键的编码方式 redis-cli object encoding long_str # 输出结果:raw