◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。
现场番机器人 Redis 数据结构:从五种基础到四种高级
- 现场番机器人
- 时间:2026-09-22 13:28:14
- 1人已阅读
---
Redis 数据结构:从五种基础到四种高级
2026 年 9 月 21 日 | 作者:wang666888
Redis 之所以强大,不只是因为快,更因为它提供了丰富的数据结构——就像仓库里不同形状的收纳盒,各有各的用处,选对了事半功倍。[citation:78.27]
---
一、五种基础数据类型
String——最基本也最常用
| 维度 | 说明 |
|:----|:------|
| 本质 | SDS(简单动态字符串),二进制安全 |
| 上限 | 512MB |
| 场景 | 缓存会话/页面数据、计数器(INCR 原子递增)、分布式锁(SETNX) |
| 注意 | 大 Value 是严重反模式;存对象需序列化 |
SET user:1001 "{\"name\":\"tom\"}"
INCR article:readcount:42
SETNX lock:order 1 EX 10
Hash——存对象属性最自然
一个 key 下挂多个 field-value 对,天然适合存对象。[citation:78.27]
HSET product:2001 price 29.9 stock 100 name "T恤"
HGET product:2001 price
场景:用户信息、商品详情。改单个字段不用整体覆盖。
List——有序队列
3.2 之后底层用 quicklist(链表 + ziplist 混合体),两端插入删除极快。[citation:78.27]
LPUSH msg:queue "hello"
RPOP msg:queue
LRANGE timeline:feed 0 9 # 取最近10条
场景:简单消息队列、最新消息列表。注意避免 LRANGE 取大范围。
Set——无序去重
查找和去重效率高,支持交集、并集、差集运算。[citation:78.27]
SADD user:1001:tags "tech" "ai"
SINTER user:1001:tags user:1002:tags # 共同标签
场景:标签系统、UV(去重)、共同关注计算。
ZSet(Sorted Set)——带权重的有序集合
底层用跳表 + 字典实现,插入和查询都很快。[citation:78.27]
ZADD leaderboard 100 "player1" 85 "player2"
ZREVRANGE leaderboard 0 9 WITHSCORES # Top 10
场景:排行榜、带权重的任务队列。注意 score 是 double 精度有限。
---
二、四种高级数据类型
| 类型 | 引入版本 | 底层本质 | 典型场景 |
|:----|:--------:|:---------|:---------|
| BitMap | 2.2+ | String 位操作 | 签到、日活统计 |
| HyperLogLog | 2.8+ | String 编码 | UV 统计(~0.81%误差) |
| GEO | 3.2+ | ZSet 封装 | 附近的人、LBS |
| Stream | 5.0+ | 独立实现 | 消息队列、事件溯源 |
BitMap——一个 bit 搞定布尔统计
用 bit 位存储数据,极度节省空间。统计 1000 万用户的日活只需要约 1.2MB。[citation:78.27]
SETBIT user:sign:20260921 1001 1 # 用户1001签到
BITCOUNT user:sign:20260921 # 统计今天签到人数
HyperLogLog——12KB 搞定亿级 UV
用极小内存(约 12KB)统计超大数量级的不重复元素。有标准误差约 0.81%,不追求精确计数时很好用。[citation:78.27]
PFADD page:uv:today "user1" "user2"
PFCOUNT page:uv:today
GEO——LBS 功能标配
底层基于 ZSet,存储经纬度,支持距离计算和范围查询。[citation:78.27]
GEOADD restaurants 116.39 39.91 "店A"
GEORADIUS restaurants 116.40 39.90 5 km # 附近5km
Stream——Redis 5.0 的专业消息队列
比 List 更完善的消息队列方案,支持消费者组、消息持久化、消息 ID 回溯,更接近 Kafka 的模型。[citation:78.27]
XADD mystream * name tom age 30
XREAD GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
---
三、底层编码:数据结构背后的数据结构
表面上是九种数据类型,底层实际由更少的编码结构组合而成。Redis 会根据数据量和元素大小自动选择编码——小数据用紧凑结构省内存,大数据切换到高效结构保性能。[citation:78.27]
三种关键底层结构
| 编码 | 说明 | 适用 |
|:----|:------|:------|
| SDS | 简单动态字符串,二进制安全,预分配空间减少内存分配次数 | String 的底层 |
| ziplist | 连续内存块组成的紧凑结构,无指针开销,但插入删除需移动内存 | 小数据量的 List/Hash/ZSet |
| quicklist | 3.2 起 List 默认实现,"链表+ziplist"混合体 | List |
| 跳表 + dict | ZSet 的黄金组合,插入查询都 O(log N) | ZSet |
| listpack | Redis 7.0 起替代 ziplist 的紧凑结构,解决级联更新问题 | 新版 Hash/List/ZSet |
编码转换阈值(Redis 7.0 默认)
String: int → embstr → raw (边界: 44字节)
List: listpack → quicklist
Hash: listpack → hashtable (默认 512 个 field)
ZSet: listpack → skiplist (默认 128 个元素)
---
四、选型速查
| 需要 | 选这个 |
|:-----|:------|
| 缓存一个值 | String |
| 存对象/字典 | Hash |
| 队列/栈 | List |
| 去重 | Set |
| 排行榜 | ZSet |
| 统计日活/签到 | BitMap |
| UV 统计(允许误差) | HyperLogLog |
| 附近的人 | GEO |
| 可靠消息队列 | Stream |
---
五、一句话总结
Redis 的九种数据结构不是各自为政,而是在 SDS、ziplist/listpack、跳表等少数底层编码上组合出来的。 小数据用紧凑编码省内存,大数据切换到高效结构保性能,这一切对用户透明。选类型时按"存什么、怎么查、要不要排序"三个问题回答,大概率不会选错。[citation:78.27]
上一篇:花开月下机器人 使用 DuckDB 分析 Parquet 文件
没有了