面试官:"说一下 Redis 的应用场景吧。" 你:"缓存!" 面试官:"......还有呢?" 你:"还是缓存......"
如果你对 Redis 的印象还停留在"缓存数据库",那这篇文章值得你花十分钟读完。作为后端开发几乎人手必用的中间件,Redis 凭借内存级的读写速度、丰富的数据结构、单线程模型,在系统中扮演着远不止"缓存"一个角色。
今天我们就来盘一盘,Redis 在真实项目中最常见的 10 大应用场景。建议先点赞收藏,面试和工作中都用得上。
01 缓存:Redis 的"本职工作"
这是最经典、使用最广泛的场景,没有之一。
在高并发系统中,如果所有请求都直接打到数据库,MySQL 大概率会扛不住。把热点数据放到 Redis 里,用户请求先查 Redis,命中则直接返回,未命中再查数据库并回写,系统吞吐量立刻上一个台阶。
典型应用:商品详情、用户信息、配置信息、热点新闻。
markdown
用户请求 → Redis 命中?→ 直接返回
↓ 未命中
查数据库 → 回写 Redis → 返回
需要注意的两个经典问题:
- 缓存穿透:查询一个数据库里根本不存在的数据。解法:缓存空值或使用布隆过滤器。
- 缓存雪崩:大量缓存同一时刻集体过期。解法:过期时间加随机值、多级缓存、热点数据永不过期。
- 缓存击穿:某个热点 key 突然失效,瞬间大量请求压向数据库。解法:互斥锁或逻辑过期。
02 排行榜:Sorted Set 的舞台
热搜榜、游戏积分榜、直播打赏榜、销量排行榜......这些"实时排序"需求,用 MySQL 的 ORDER BY 又慢又重,而 Redis 的 ZSet(有序集合) 几乎是为它量身定做的。
ZSet 中每个成员都关联一个 score,Redis 会自动按 score 排序:
bash
ZADD rank:game 980 "张三"
ZADD rank:game 1200 "李四"
ZINCRBY rank:game 50 "张三" # 给张三加 50 分
ZREVRANGE rank:game 0 9 WITHSCORES # 取 Top10
无论是取前 N 名,还是查询某人的排名(ZREVRANK),都是毫秒级完成。这就是为什么几乎所有排行榜功能背后都站着一个 Redis。
03 计数器与限流:高并发的数字游戏
文章阅读量、视频点赞数、接口限流、秒杀库存------这些场景的特点是写操作极其频繁 。如果每次都 UPDATE 数据库,行锁会让性能急剧下降。
Redis 的 INCR 是原子操作,天生适合干这个:
ruby
INCR article:1001:views # 阅读量 +1
INCRBY seckill:sku:8888 -1 # 秒杀库存 -1
结合过期时间,还可以轻松实现滑动窗口限流:
sql
# 60 秒内同一用户最多请求 100 次
INCR rate:user:1001
EXPIRE rate:user:1001 60
04 分布式锁:多实例之间的"红绿灯"
单机应用里,一个 synchronized 就能解决线程安全问题。但当服务部署成集群、跑在多台机器上时,JVM 锁就失效了,这时就需要一把跨进程的分布式锁。
Redis 实现锁的核心命令:
sql
SET lock:order:1234 "唯一标识" NX EX 10
NX:key 不存在才设置,保证只有一个客户端抢锁成功;EX 10:10 秒自动过期,防止持锁者宕机后死锁。
实际项目中更推荐直接使用成熟的 Redisson,它提供了看门狗自动续期、可重入锁、读写锁等机制,避免自己手写锁带来的各种坑。
适用场景:扣库存、定时任务防重复执行、防重复下单。
05 消息队列:轻量级的异步解耦
提到消息队列你可能想到 Kafka、RabbitMQ,但 Redis 同样可以承担轻量级队列的职责:
- List :
LPUSH生产消息、BRPOP阻塞消费,简单的点对点队列; - Pub/Sub:发布订阅,支持一对多广播,但消息不持久化,消费者离线就丢;
- Stream(Redis 5.0+):借鉴了 Kafka 的设计,支持消息持久化、消费组、确认机制,是目前最推荐的方案。
yaml
XADD orders * userId 1001 amount 99 # 生产
XREADGROUP GROUP g1 c1 COUNT 10 STREAMS orders > # 消费
选型建议:对可靠性要求极高、数据量大的核心链路用 Kafka/RocketMQ;一般业务的异步削峰、日志上报,Redis Stream 完全够用。
06 Session 共享:解决分布式登录态
单机时代,用户登录信息存在服务器的 Session 里没毛病。可一旦服务集群化,用户这次请求落在 A 机器、下次落在 B 机器,登录态就丢了。
经典解法是统一把 Session 存入 Redis:
- 所有应用实例共享同一份登录状态;
- 利用 Redis 过期时间控制登录有效期;
- Spring Session 等框架几乎可以做到无缝接入。
这也是为什么 Redis 是各类 SSO、登录系统背后的常客。
07 社交关系:集合运算的艺术
粉丝、关注、共同好友、可能认识的人------这类社交关系用 Set 来建模再合适不过:
yaml
SADD follow:1001 2002 2003 # 用户1001关注了谁
SADD fans:2002 1001 # 用户2002的粉丝
SINTER follow:1001 follow:1002 # 共同关注
SINTER(交集)算共同好友,SDIFF(差集)算"我关注了但他没关注",SPOP 还能实现抽奖。一系列集合运算全在服务端原子完成,性能极高。
08 最新列表与消息流
朋友圈动态、最新评论、站内信收件箱......这类"取最新 N 条"的需求,用 List 的 LPUSH + LRANGE 即可轻松实现:
bash
LPUSH feed:1001 "动态A" "动态B"
LTRIM feed:1001 0 999 # 只保留最新 1000 条
LRANGE feed:1001 0 9 # 取最新 10 条
配合分页可以不断下拉加载。微博早期 TimeLine 推模式,核心思路就与此类似。
09 地理位置:附近的人和店
"附近的餐厅""附近的骑手""打车时匹配最近的车辆"------Redis 从 3.2 开始内置了 GEO 类型,底层基于 ZSet + GeoHash 实现:
arduino
GEOADD shops 116.40 39.90 "火锅店A"
GEOSEARCH shops FROMMEMBER 我的位置 BYRADIUS 3 km WITHDIST
直接就能查出"3 公里内的店铺及距离",开发一个"附近的 XX"功能,甚至不需要引入专门的地理位置数据库。
10 全局唯一 ID 与其他妙用
除了上面九大场景,Redis 在很多细节处也能派上用场:
- 全局唯一 ID :利用
INCR或号段模式生成趋势递增的订单号、分布式主键; - 购物车 :
HSET cart:用户ID 商品ID 数量,Hash 天然适配; - 签到打卡 :Bitmap 一个月只占几十 bit,
BITCOUNT统计签到天数; - 海量数据布隆过滤器:判断元素"一定不存在或可能存在";
- UV 统计(HyperLogLog) :用极小内存完成亿级数据去重计数,误差约 0.81%。
可以说,只要涉及"快、准、高频"的需求,Redis 总能在架构图里找到自己的位置。
写在最后
我们用一张表快速回顾:
| 场景 | 核心数据结构/命令 |
|---|---|
| 热点数据缓存 | String + 过期策略 |
| 排行榜 | ZSet |
| 计数器 / 限流 / 秒杀 | INCR、DECR |
| 分布式锁 | SET NX EX / Redisson |
| 消息队列 | List / Pub-Sub / Stream |
| Session 共享 | String(带 TTL) |
| 社交关系 | Set 交并差集 |
| 最新列表 | List |
| 附近的人/店 | GEO |
| 签到、UV、购物车 | Bitmap / HLL / Hash |
最后提醒一句:Redis 很强大,但不是银弹。它是内存数据库,成本远高于磁盘存储,不适合存放海量冷数据;持久化和主从切换期间也可能丢数据。选型时想清楚业务的容量、一致性和可靠性要求,才能让这把"瑞士军刀"真正发挥威力。
如果这篇文章对你有帮助,欢迎点赞、在看、转发三连,你的支持是我持续输出的最大动力~
你在项目中还把 Redis 用在了什么"骚操作"上?欢迎在评论区聊聊!