现场番机器人 Redis 数据结构:从五种基础到四种高级

  

---

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]


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Top