常见数据结构
概览
| 类型 | 用途 | 底层实现 |
| String(字符串) 可存储字符串、整数或浮点数 |
计数器 分布式锁 存储序列化对象 |
int(如果存的全数字) SDS 简单动态字符串 |
| Hash(哈希) 可存储多个键值对 |
缓存对象 | ZipList 压缩列表 (连续占用内存,因此存储的元素不能太多) 一旦元素存储太多,会转为 Dict 哈希表 Redis 7.0 引入了 listpack 取代 ZipList 压缩列表 |
| List(列表) 可重复、(插入和取出)有序 |
朋友圈点赞/评论列表 | QuickList 快速列表:一种双向链表,每个节点是一个压缩列表 结合了压缩列表和双向链表的优点 |
| Set(集合) 不可重复,无序,求交集、差集等 |
求共同关注 去重 |
若集合中的元素都是整数且元素个数小于 512 : IntSet 整数集合 否则:Dict 哈希表(Set是单列集合,Dict的每个节点是存键值对 的,那么其实是只用了键来存元素,值都设为null) |
| ZSet(有序集合) 不可重复,每个元素都关联一个分数 自动按照分数排序元素 |
排行榜 | 当元素数量小于128,每个元素小于64字节:ZipList 压缩列表 否则:Dict + SkipList,存储两份数据,Dict 和 SkipList 各一份 为什么要存储两份数据?因为这是它的特性需求 - 利用Dict去键值查询:根据元素查分数 - 利用SkipList范围查询 (快速跳过大量无关节点,定位范围的起始点): - 获取指定分数区间的元素 - 获取排名在指定区间的元素 Redis 7.0 引入了 listpack 取代 ZipList 压缩列表 |
| BitMap(位图) 存储二进制位 |
布隆过滤器 用户签到记录 |
|
| HyperLogLog(基数估算) 基数统计 |
网页UV计数统计 | |
| Geo 可存储地理位置信息(如经纬度) |
附近的人/地点查询 地理位置范围查询 |
|
| Stream(流) | 消息队列 |
String
- 用途:存储整数、字符串和浮点数
- 本质:二进制安全的动态字符串
- 底层实现:SDS
Simple Dynamic String
Redis并没有使用C语言的char *, 而是自己设计了一个结构。
1 | struct sdshdr { |
SDS的优势:
- O(1)时间获取长度
- 杜绝缓冲区溢出
- 二进制安全:不依赖
\0结尾,可以存任意字节
二进制安全:一个系统或函数能够正确处理任意字节序列(包括 \0 字符),而不会因为遇到特殊字节(如空字符)而提前截断或出错
Hash
- 缓存键值对
- 用途:存储对象
- 底层实现:当存储元素比较少时,使用ZipList;元素较多时,使用Hashtable
Zip List
压缩链表:是Redis为节省内存而设计的一种连续内存、紧凑存储的双向链表结构
压缩 == 去指针 + 连续存储
(原文包含外部图片引用,未转换为博客资源)
- bytes:总字节数
- tail:最后一个实体的offset
- len:实体的个数
- end:固定值 0xFF 表示结尾
List
- 用途:联系人点赞
- 元素是String
- 有序
- 可重复
- 底层实现:双向链表(quick list)
Quick List
外层是双向链表,每个节点是一个压缩列表
Set
- 用途:去重
- O(1)时间判断存在性
- 底层实现:元素个数小于512,intSet;大于512,HashTable;
Dict 哈希表
1 | typedef struct dict { |
Set中的每个元素存储到Dict的键上,value为null。
rehash:
Dict会收缩或扩容,此时需要重新计算key的位置;redis采用的是一种渐进式rehash的过程:
不一次性迁移完所有数据,而是每次(增删改查)中,顺带迁移。
- 新增操作:直接在ht[1](新哈希表)中新增
- 删除、查找、修改:在ht[1] 和 ht[2]中依次进行
Zset
1 | typedef struct zset { |
- 每个元素关联一个分数
- 用途:排行榜
- 当元素数量小于128,每个元素小于64字节:ZipList 压缩列表;否则:Dict + SkipList,存储两份数据,Dict 和 SkipList 各一份
SkipList
(原文包含外部图片引用,未转换为博客资源)
跳表:一种多层链表
HyperLogLog
HyperLogLog(HLL) 是 Redis 中一种用于高性能、低内存消耗的基数统计(Cardinality Estimation)的概率数据结构。它能以极小的内存(通常 12KB 左右)估算集合中不重复元素的数量(即 UV,Unique Visitor)
核心思想:通过观察哈希值的“稀有程度”来反推总体数量