高 基础
Redis应用场景总结#
一句话答案#
缓存(String/Hash)、分布式锁(SETNX)、计数器(INCR)、排行榜(ZSet)、Session、延迟队列(ZSet)、限流。
核心要点
数据结构 → 应用场景映射:
| 数据结构 | 典型场景 | 核心命令 |
|---|---|---|
| String | 缓存对象、计数器、分布式锁、Session | SET/GET、INCR、SETNX |
| Hash | 对象属性存储(用户画像)、购物车 | HSET/HGET/HMGET |
| List | 消息队列、最新动态、任务队列 | LPUSH/BRPOP/LRANGE |
| Set | 去重、共同好友、抽奖 | SADD/SINTER/SRANDMEMBER |
| ZSet | 排行榜、延迟队列、带权重优先级 | ZADD/ZREVRANGE/ZRANGEBYSCORE |
6 个典型业务实现:
# 1. 缓存(String)
SET user:1001 "{json}" EX 3600 # 缓存用户信息 1 小时
# 2. 分布式锁(String)
SET lock:order:123 uuid NX EX 30 # 加锁:原子设置 + 过期时间
# 3. 计数器(String)
INCR article:1001:views # 文章浏览量 +1(原子操作)
# 4. 排行榜(ZSet)
ZADD leaderboard 1000 user1 # 写入分数
ZREVRANGE leaderboard 0 9 WITHSCORES # 取 Top10
# 5. 延迟队列(ZSet)
ZADD delay_queue <执行时间戳> task_id # 生产者写入
ZRANGEBYSCORE delay_queue 0 <当前时间戳> # 消费者轮询到期任务
# 6. 限流(String + Lua)
INCR rate_limit:{userId}:{minute} # 固定窗口计数
# 或用 ZSet 滑动窗口 / Lua 实现令牌桶bash选型原则: 选对数据结构匹配业务场景,底层编码方面小数据量用 listpack 省内存,超过阈值自动转 hashtable 或 skiplist。
面试回答(2分钟版)
Redis 的应用场景本质上是围绕它的数据结构来选型的。String 最常用于缓存对象和计数器,比如用 INCR 做接口访问量统计;Hash 适合存对象的多个字段,像用户画像按 field 存取单个属性避免整体序列化;List 可以做消息队列但一般用专业 MQ 替代;Set 用于去重和集合运算,比如共同好友就是两个 Set 求交集;ZSet 是最灵活的,score 排序天然适合排行榜,把时间戳当 score 还能做延迟队列。除了数据结构,Redis 还常用于分布式锁(SETNX+过期时间)、分布式 Session(Spring Session + Redis)、限流(滑动窗口用 ZSet 或令牌桶用 Lua 脚本)。选型的核心原则是选对数据结构匹配业务场景,底层编码方面小数据量用 listpack 省内存,超过阈值自动转 hashtable 或 skiplist。
追问与易错
追问方向:
- “排行榜数据量大怎么办?”→ 单个 ZSet 元素过多会成为大 Key,按时间维度分片(日榜/周榜/月榜各一个 ZSet);超大规模排行榜考虑分段存储或用 ES/ClickHouse 做离线排行
- “延迟队列用 ZSet 什么问题?”→ 需要轮询(ZRANGEBYSCORE)消耗 CPU,多消费者竞争同一任务需要用 Lua 保证原子取出;不支持 ACK 机制,消费失败无法自动重试;生产环境大规模延迟任务推荐 RocketMQ 延迟消息
- “分布式限流用 Redis 怎么做?”→ 固定窗口用 INCR+EXPIRE 计数;滑动窗口用 ZSet 存请求时间戳,ZRANGEBYSCORE 统计窗口内请求数;令牌桶用 Lua 脚本实现原子的取令牌逻辑
易错点:
- ❌ Redis 能解决所有缓存问题——需考虑容量和一致性
- ❌ 所有场景都用 String——选对数据结构很重要