Redis 实用场景全解析:不只是缓存
Redis 常被当作"缓存工具",但它的能力远不止于此。凭借丰富的数据结构和亚毫秒级响应速度,Redis 已经成为高并发系统里的多面手。本文梳理几个在实际项目中最常见、最有价值的 Redis 使用场景。
1. 缓存:降低数据库压力
这是 Redis 最经典的用法。把数据库中读多写少的数据(用户信息、商品详情、配置项等)放进 Redis,请求先查缓存,命中则直接返回,未命中再查数据库并回写缓存。
GET product:1001
# 未命中 -> 查数据库 -> SET product:1001 "{...}" EX 3600
需要注意的三个经典问题:
- 缓存穿透:查询不存在的数据,请求穿过缓存打到数据库。可以对空结果也做短期缓存,或用布隆过滤器提前拦截。
- 缓存击穿:热点 key 过期瞬间大量请求涌入数据库。可以给热点数据加互斥锁重建,或设置逻辑过期不做物理过期。
- 缓存雪崩:大批 key 同时过期导致数据库瞬间压力暴增。给过期时间加上随机值可以有效分散。
2. 会话存储(Session Store)
在分布式部署下,用户请求可能被负载均衡到任意一台服务器,本地 Session 无法共享。把 Session 统一存到 Redis,配合过期时间自动清理,就能让任意节点读取同一份会话状态,这也是 Session 集中化管理的标准做法。
SET session:abc123 "{userId:1, role:admin}" EX 1800
3. 分布式锁
多个服务实例同时操作同一资源时,需要一把"跨进程"的锁。Redis 的 SET key value NX EX seconds 可以原子地实现加锁,释放锁时用 Lua 脚本保证"判断持有者+删除"的原子性,避免误删别人的锁。
SET lock:order:1001 "worker-7" NX EX 10
生产环境更严谨的方案会用 Redlock 算法或者直接采用 Redisson 这类封装好的客户端,处理时钟漂移、锁续期(看门狗)等边界问题。
4. 排行榜与计分(Sorted Set)
游戏积分榜、热搜榜、销量排行这类"按分数排序"的场景,天生适合用 Sorted Set。一条 ZADD 写入分数,ZREVRANGE 就能拿到排名区间,ZRANK 能查任意成员的名次,复杂度都是对数级别。
ZADD leaderboard 9800 "player:alice"
ZREVRANGE leaderboard 0 9 WITHSCORES # 取前十名
ZRANK leaderboard "player:bob" # 查某玩家排名
5. 计数器与限流
点赞数、浏览量、库存扣减这类高频自增场景,用 INCR/DECR 一条命令就能原子完成,避免了"读出来+加一+写回去"的竞态问题。
限流则常用滑动窗口或令牌桶算法配合 Redis 实现,比如结合 INCR + EXPIRE 做简单的固定窗口限流:
INCR rate:user:1001
EXPIRE rate:user:1001 60 # 仅在第一次自增时设置
# 若返回值超过阈值则拒绝请求
更精细的场景可以用 Redis 自带的 CL.THROTTLE(RedisCell 模块)或 Lua 脚本实现漏桶/令牌桶算法。
6. 消息队列与发布订阅
Redis 的 List(LPUSH/BRPOP)可以当作简单的任务队列,Stream(XADD/XREADGROUP)则支持消费组、消息确认、历史回溯,适合做轻量级的消息中间件替代方案。Pub/Sub 则适合广播型场景,比如后台配置变更通知所有服务实例热更新。
XADD orders * orderId 1001 status "paid"
XREADGROUP GROUP g1 consumer-1 COUNT 10 STREAMS orders >
需要强可靠、重投递、死信队列等企业级特性时,建议还是选择 Kafka、RabbitMQ 这类专职消息队列,Redis Stream 更适合中小规模场景。
7. 地理位置服务
Redis 的 Geo 数据结构(底层基于 Sorted Set + Geohash)可以存储经纬度,并直接查询"附近的人""附近的店"。
GEOADD stores 116.397 39.908 "store:1"
GEOSEARCH stores FROMLONLAT 116.4 39.9 BYRADIUS 5 km ASC
外卖、打车、社交类应用中"附近门店/附近的人"功能大多是这样实现的。
8. 去重与统计(HyperLogLog / Bitmap)
统计网站每日 UV、独立访客这种"只关心去重后数量、不关心具体是谁"的场景,用 HyperLogLog 只需要 12KB 左右的内存就能在标准误差 0.81% 内估算百万级基数,比直接用 Set 存储省内存得多。
PFADD uv:20260710 "user:1001" "user:1002"
PFCOUNT uv:20260710
而用户签到、连续登录天数这类场景,用 Bitmap 一个 bit 代表一天,SETBIT/BITCOUNT 几行命令就能统计出月活跃天数。
9. 延迟任务与定时提醒
利用 Sorted Set 把"执行时间戳"作为分数,"任务内容"作为成员,一个后台线程定期 ZRANGEBYSCORE 取出到期任务并执行,就实现了一个简易的延迟队列,常用于订单超时取消、优惠券到期提醒等场景。
ZADD delay_tasks 1752134400 "order:1001:cancel"
ZRANGEBYSCORE delay_tasks 0 <当前时间戳>
小结
从最基础的缓存加速,到分布式锁、排行榜、限流、消息队列、地理位置、去重统计、延迟任务,Redis 凭借 String、Hash、List、Set、Sorted Set、Bitmap、HyperLogLog、Stream、Geo 这些数据结构,几乎能覆盖高并发系统里大部分"快速读写+简单逻辑"的需求。选型时的关键不是"能不能用 Redis 实现",而是评估数据规模、持久化要求和可靠性诉求后,判断 Redis 是否是这个场景下最合适的工具。


