Skip to content

Redis 数据类型与底层实现

Redis 数据类型总览

Redis提供了8种数据类型,每种类型都有多种底层实现(编码方式)。

字符串(String)

底层实现

  1. int:整数值,8字节长整型
  2. embstr:短字符串,< 44字节,使用嵌入式SDS
  3. raw:长字符串,> 44字节,使用普通SDS

SDS(Simple Dynamic String)

c
struct sdshdr {
    int len;     // 已使用长度
    int free;    // 未使用长度
    char buf[];  // 实际数据
};

优势

  • O(1)获取长度
  • 空间预分配 + 惰性释放
  • 二进制安全(不依赖\0结尾)

列表(List)

编码方式

  1. ziplist:压缩列表,元素少时使用
  2. quicklist:3.2+版本默认,ziplist的链表
  3. linkedlist:早期版本使用

quicklist结构

+---+---+---+---+---+---+---+
| 2 | 5 | 8 | 1 | 3 | 7 | 9 |
+---+---+---+---+---+---+---+
  |   |   |   |   |   |   |
 v1   v2  v3  v4  v5  v6  v7

每个节点是一个ziplist,节点数可配置(默认-2表示8KB)

编码转换条件

  • 元素数量 > 512 或 单元素 > 64字节:ziplist → quicklist

哈希(Hash)

编码方式

  1. ziplist:元素少时,键值对依次存放
  2. hashtable:元素多时,使用哈希表

渐进式rehash

c
// rehash过程分两次完成
dict rehash分150ms步进行,每步迁移一个bucket

步骤

  1. 创建新哈希表
  2. 设置rehashidx = 0
  3. 每次访问时迁移一个bucket
  4. 迁移完成则释放旧表

集合(Set)

编码方式

  1. intset:整数集合,元素都是整数
  2. hashtable:哈希表,通用

编码转换

  • 元素数量 > 512 或 有非整数元素:intset → hashtable

有序集合(Zset)

编码方式

  1. ziplist:元素少时
  2. skiplist + dict:元素多时

编码转换

  • 元素数量 >= 128 或 元素 >= 64字节:ziplist → skiplist

面试考点

Q1: Redis数据类型的编码转换时机?

答案

类型转换条件
String44字节
List512元素或64字节
Hash512元素或64字节
Set512元素或非整数
Zset128元素或64字节

Q2: 为什么String类型用embstr?

答案

  • 减少内存分配次数
  • embstr将SDS和redisObject分配在连续内存
  • 只读操作无需内存分离

Q3: List用quicklist的好处?

答案

  1. 内存更紧凑(ziplist)
  2. 插入/删除O(1)(链表)
  3. 取值性能好(局部性原理)

最后更新: