Appearance
Redis 数据类型与底层实现
Redis 数据类型总览
Redis提供了8种数据类型,每种类型都有多种底层实现(编码方式)。
字符串(String)
底层实现
- int:整数值,8字节长整型
- embstr:短字符串,< 44字节,使用嵌入式SDS
- raw:长字符串,> 44字节,使用普通SDS
SDS(Simple Dynamic String)
c
struct sdshdr {
int len; // 已使用长度
int free; // 未使用长度
char buf[]; // 实际数据
};优势:
- O(1)获取长度
- 空间预分配 + 惰性释放
- 二进制安全(不依赖\0结尾)
列表(List)
编码方式
- ziplist:压缩列表,元素少时使用
- quicklist:3.2+版本默认,ziplist的链表
- linkedlist:早期版本使用
quicklist结构
+---+---+---+---+---+---+---+
| 2 | 5 | 8 | 1 | 3 | 7 | 9 |
+---+---+---+---+---+---+---+
| | | | | | |
v1 v2 v3 v4 v5 v6 v7每个节点是一个ziplist,节点数可配置(默认-2表示8KB)
编码转换条件
- 元素数量 > 512 或 单元素 > 64字节:ziplist → quicklist
哈希(Hash)
编码方式
- ziplist:元素少时,键值对依次存放
- hashtable:元素多时,使用哈希表
渐进式rehash
c
// rehash过程分两次完成
dict rehash分150ms步进行,每步迁移一个bucket步骤:
- 创建新哈希表
- 设置rehashidx = 0
- 每次访问时迁移一个bucket
- 迁移完成则释放旧表
集合(Set)
编码方式
- intset:整数集合,元素都是整数
- hashtable:哈希表,通用
编码转换
- 元素数量 > 512 或 有非整数元素:intset → hashtable
有序集合(Zset)
编码方式
- ziplist:元素少时
- skiplist + dict:元素多时
编码转换
- 元素数量 >= 128 或 元素 >= 64字节:ziplist → skiplist
面试考点
Q1: Redis数据类型的编码转换时机?
答案:
| 类型 | 转换条件 |
|---|---|
| String | 44字节 |
| List | 512元素或64字节 |
| Hash | 512元素或64字节 |
| Set | 512元素或非整数 |
| Zset | 128元素或64字节 |
Q2: 为什么String类型用embstr?
答案:
- 减少内存分配次数
- embstr将SDS和redisObject分配在连续内存
- 只读操作无需内存分离
Q3: List用quicklist的好处?
答案:
- 内存更紧凑(ziplist)
- 插入/删除O(1)(链表)
- 取值性能好(局部性原理)
