Skip to content

Redis 数据结构与使用场景

这篇笔记专门整理 Redis 里最核心的一条主线:数据结构怎么选

Redis 很多能力看起来像“命令很多”,但真正落到工程实践,最关键的问题其实是:当前这类数据,到底应该放成什么结构,才能既容易操作,又能保持性能稳定。


1. 🌟 为什么 Redis 的数据结构很重要

Redis 的优势不只是“在内存里”,还在于它提供了多种针对高频操作优化过的数据结构。

这意味着:

  1. 结构选对了,读写会很自然
  2. 结构选错了,代码会变别扭,性能也容易变差

例如排行榜用 ZSet 就很自然;如果硬用 String 加应用端排序,也不是不能做,但复杂度和性能都不会太友好。

所以 Redis 里的很多设计题,本质上不是“有没有办法实现”,而是:是不是选中了最贴合访问模式的数据结构。


2. 🌟 5 种基础类型

2.1 String

String 是 Redis 里最常见的类型,适合:

  1. 缓存单个值
  2. 计数器
  3. 分布式锁基础实现
  4. 简单标志位

常见场景:

  1. 商品详情缓存
  2. 短信验证码
  3. 点赞数、阅读数

它的优势是简单、通用,但如果一个对象字段很多、局部更新频繁,就不一定是最优选择。

2.2 Hash

Hash 更适合表示对象的多个字段,例如:

  1. 用户信息
  2. 配置项
  3. 订单摘要

它的好处是:

  1. 结构清晰
  2. 可以按字段更新
  3. 比把所有字段都硬塞成一个大 JSON 更容易做局部操作

2.3 List

List 适合按顺序维护一组元素,典型场景包括:

  1. 简单消息队列
  2. 最近访问记录
  3. 时间顺序消息流

但如果你既要顺序,又要去重,还要排序,List 往往就不是最贴切的结构了。

2.4 Set

Set 最适合这些问题:

  1. 去重
  2. 成员关系判断
  3. 交集、并集、差集计算

例如:

  1. 用户标签集合
  2. 已点赞用户集合
  3. 共同好友或共同关注分析

2.5 ZSet

ZSet 是带分数的有序集合,非常适合:

  1. 排行榜
  2. 按权重排序
  3. 延迟队列基础实现
  4. 优先级调度

它之所以经典,是因为它同时保留了:

  1. 成员唯一性
  2. 分数排序能力
  3. 范围查询能力

3. 🌟 不是只有 5 种:Redis 里还有几类非常常见的能力

3.1 Bitmap

Bitmap 很适合做大规模布尔位统计,例如:

  1. 用户签到
  2. 用户是否活跃
  3. 某天是否登录

它的核心价值是:用非常紧凑的空间表示大量 0/1 状态。

3.2 HyperLogLog

HyperLogLog 适合做近似去重统计,例如:

  1. UV 统计
  2. 独立访客数量估算

它的重点不在“绝对精确”,而在:

  1. 空间占用很小
  2. 可以接受一定误差

如果业务要求绝对精确去重,就不能直接用它替代普通集合。

3.3 GEO

GEO 适合位置类场景,例如:

  1. 附近门店
  2. 附近骑手
  3. 附近的人

它让 Redis 在轻量位置检索场景里也能承担一部分能力。

3.4 Stream

Stream 是 Redis 较新的重要能力之一,适合:

  1. 消息流
  2. 消费组
  3. 多消费者处理

它比简单的 List 更适合消息消费场景,但如果业务对消息可靠性、积压治理和生态要求特别高,通常还是要结合更专业的 MQ 做选型。


4. 一个更实用的结构选型表

需求更适合的结构原因
单值缓存、计数器String简单直接,通用性高
对象字段存储Hash字段级更新更自然
顺序消息或最近记录List天然有序
去重和集合关系Set成员唯一,集合运算方便
排行榜、权重排序ZSet有序且支持范围查询
海量布尔位状态Bitmap空间占用更紧凑
近似 UV 去重统计HyperLogLog低成本近似统计
附近位置检索GEO原生位置计算能力
消息流、消费组Stream更适合流式消费

5. 🌟 结构选型时最容易忽略的几个问题

5.1 不是能存进去就算合适

例如一个对象,理论上可以直接序列化成 String,也可以拆成 Hash
区别不在“能不能存”,而在:

  1. 是否需要局部更新
  2. 是否需要按字段读取
  3. 是否追求结构清晰

5.2 排序需求通常决定你是否应该用 ZSet

很多设计一开始看起来是“只要存个集合”,但一旦业务开始要求:

  1. 按分数排名
  2. 查前 100 名
  3. 查某个分值区间

这时候 ZSet 往往就比 SetList 更合适。

5.3 大量状态位不要滥用普通集合

像签到、活跃状态这类问题,如果用 Set 也能做,但数据量上来后,Bitmap 往往更省空间。

5.4 Stream 能解决一部分消息问题,但不等于通用 MQ

Stream 很强,但它更适合 Redis 生态内的轻量流式处理。
如果业务依赖复杂消息治理、超大堆积、跨系统可靠投递,仍然要结合专业 MQ 评估。


6. 一份实用的数据结构检查清单

可以优先检查这些问题:

  1. 这个结构是否贴合主要读写模式
  2. 是否需要排序、去重或范围查询
  3. 是否需要局部更新
  4. 是否有大规模布尔位或近似去重统计需求
  5. 这个结构在数据量上来后是否还稳定

Redis 数据结构设计真正的关键,不是记住多少命令,而是把“数据形态”和“访问模式”对齐起来。

基于 VitePress 构建的个人技术笔记。