Redis 核心数据结构与典型场景
下面是为面试准备的 Redis 核心数据结构与典型场景 速查表。每个类型都给出了一句话场景 + 具体例子,方便你面试时清晰、有说服力地阐述。
1. String(字符串)
特点:最基础,可存文本、整数、浮点、二进制(图片等)。
核心能力:SET/GET、INCR/DECR、SETEX(带过期)、MSET 批量。
| 场景 | 例子 |
|---|---|
| 分布式锁 | SET lock:product_1001 uuid NX EX 10(原子加锁+过期) |
| 计数器 | 文章阅读量:INCR article:123:views;限流滑动窗口(配合时间戳) |
| 对象缓存(JSON) | 用户信息:SET user:1001 '{"name":"张三","age":25}' (适合整体读写的场景) |
| 全局ID生成 | INCR global:id:order 获取唯一订单号 |
| Session 共享 | SETEX session:abc123 3600 "user_data"(带过期时间的用户会话) |
example
SET user:1001 '{"name":"张三","age":25}'
GET user:1001
# "{\"name\":\"张三\",\"age\":25}"
INCR article:123:views
# (integer) 1
SET lock:product_1001 uuid NX EX 10
# OK
2. Hash(哈希)
特点:field-value 对的集合,适合描述一个对象的多字段。
核心能力:HSET/HGET、HINCRBY、HGETALL、HDEL。
| 场景 | 例子 |
|---|---|
| 缓存数据库记录(对象) | 用户信息:HSET user:1001 name "李四" age 30 level 5,单独修改 level 时用 HINCRBY |
| 购物车 | Key=cart:用户123,field=商品ID,value=数量。HINCRBY cart:123 10086 1 增加商品 |
| 配置项存储 | 系统配置:HSET config:system max_login 3 timeout 30 theme dark |
| 对象部分字段更新 | 只更新用户邮箱:HSET user:1001 email new@xx.com,无需重传整个对象 |
example
HSET user:1001 name "张三" age 25 email "zhang@example.com"
HGETALL user:1001
# 1) "name"
# 2) "张三"
# 3) "age"
# 4) "25"
# 5) "email"
# 6) "zhang@example.com"
3. List(列表)
特点:有序、可重复,底层为双向链表或 quicklist。左右两边操作快。
核心能力:LPUSH/RPUSH、LPOP/RPOP、LRANGE、BLPOP(阻塞)。
| 场景 | 例子 |
|---|---|
| 消息队列(简单) | 生产者 RPUSH queue:order "order-123",消费者 LPOP queue:order;或用 BLPOP 阻塞等待 |
| 最新动态 / 时间线 | 微博最新评论:LPUSH post:1001:comments "{id:1,text:'good'}" + LTRIM 保留最近100条 |
| 操作日志 | 记录用户最近操作:LPUSH user:456:actions "login" + LTRIM 限制1000条 |
| 栈或队列的实现 | 栈:LPUSH + LPOP;队列:RPUSH + LPOP |
example
RPUSH queue:order "order-123"
LPOP queue:order
# "order-123"
LPUSH post:1001:comments "good" "nice"
LRANGE post:1001:comments 0 -1
# 1) "nice"
# 2) "good"
4. Set(集合)
特点:无序、元素唯一。支持交、并、差集运算。
核心能力:SADD/SREM、SISMEMBER、SMEMBERS、SINTER、SUNION。
| 场景 | 例子 |
|---|---|
| 标签系统 | 文章标签:SADD article:2001:tags "redis" "database";给用户推荐相似文章:SINTER user:1:tags user:2:tags |
| 共同好友 / 关注 | 用户A的关注集合 SADD follow:A B C,用户B的关注集合,SINTER 得共同关注 |
| 抽奖 / 去重 | 抽奖池:SADD lucky:2025 "userID1" "userID2",SRANDMEMBER 随机抽奖 |
| 唯一性判断 | 判断昵称是否被占用:SISMEMBER nicknames "老王" |
| 黑名单 / 白名单 | SADD blacklist ip:192.168.1.10,请求时 SISMEMBER 判断 |
example
SADD article:2001:tags "redis" "database"
SISMEMBER article:2001:tags "redis"
# (integer) 1
# follow:A = {B, C},follow:B = {C, D}(成员是「被关注的人」,不是 key 名)
SADD follow:A B C
SADD follow:B C D
SINTER follow:A follow:B
# 1) "C"
5. Sorted Set(有序集合)
特点:每个元素关联一个 score(分数),按分数排序。元素唯一,分数可重复。
核心能力:ZADD、ZRANGE、ZREVRANGE、ZINCRBY、ZRANK、ZREVRANK、ZRANGEBYSCORE。
| 场景 | 例子 |
|---|---|
| 排行榜 | 游戏积分榜:ZADD rank:game1 1000 "playerA" 2000 "playerB";ZREVRANGE rank:game1 0 9 取前十 |
| 延迟消息队列 | 用 score 存储执行时间戳。消费者 ZRANGEBYSCORE job:delay 0 当前时间 LIMIT 0 1 取到期任务 |
| 带权重的任务调度 | 任务优先级:ZADD tasks 3 "task1" 1 "task2"(score 越小越优先) |
| 热点数据排序 | 文章热度榜:每次点赞 ZINCRBY hot:news 1 article:101,定时取 Top N |
| 范围查询 | 按年龄范围筛选用户:ZADD users:age 25 "userA" 30 "userB";ZRANGEBYSCORE users:age 20 30 |
example
ZADD rank:game1 1000 "playerA" 2000 "playerB"
ZREVRANGE rank:game1 0 1 WITHSCORES
# 1) "playerB"
# 2) "2000"
# 3) "playerA"
# 4) "1000"
ZINCRBY hot:news 1 article:101
# "1"
6. 其他补充(面试加分)
Bitmaps(基于 String)
- 场景:用户签到、在线状态(每个位表示某一天的签到)。
- 例子:
SETBIT sign:user:1001 0 1(2025-01-01 签到),BITCOUNT sign:user:1001统计签到次数。
example
SETBIT sign:user:1001 0 1
BITCOUNT sign:user:1001
# (integer) 1
HyperLogLog
- 场景:UV 统计(独立访客数),允许一定误差。
- 例子:
PFADD page:home:20250201 "user_ip_1" "user_ip_2",PFCOUNT page:home:20250201。
example
PFADD page:home:20250201 "user_ip_1" "user_ip_2"
PFCOUNT page:home:20250201
# (integer) 2
Geo
- 场景:附近的人 / 位置服务。
- 例子:
GEOADD location:stores 116.39 39.90 "storeA",GEORADIUS location:stores 116.40 39.91 5 km。
example
GEOADD location:stores 116.39 39.90 "storeA"
GEORADIUS location:stores 116.40 39.91 5 km
# 1) "storeA"
# 2) "0.1234"
面试小贴士(如何回答)
- 先给出分类:Redis 有 5 种基础类型:String、Hash、List、Set、Sorted Set。
- 按“场景需求”反推类型:
- 需要计数/缓存简单值 → String
- 需要存对象的多个字段且单独修改 → Hash
- 需要有序、可重复、队列/栈行为 → List
- 需要唯一性、集合运算(共同好友) → Set
- 需要排序、权重、排行榜 → Sorted Set
- 结合实际项目:比如“我们之前用 Sorted Set 做实时小时榜,用 Hash 做用户信息缓存,用 String 做分布式锁”。
- 可以补充内存优化和过期策略(例如 Hash 小数据用 ziplist,List 限制长度防止内存膨胀)。
把这些例子记熟,面试时随口举一两个场景,就能体现你对 Redis 的深入理解。