# Redis 通常应用于哪些场景?
8 min read
Table of Contents
Redis 通常应用于哪些场景?
Redis 应用场景详解
【核心定义】
Redis 是一款基于内存、支持多种数据结构、具备持久化能力的高性能键值存储数据库,其核心价值在于通过内存操作和高效数据结构,为应用提供亚毫秒级的数据访问速度,常被用作缓存、消息中间件和实时数据处理系统。
【关键要点】
- 缓存(Cache):作为数据库前置缓存,缓解后端压力,提升读取性能。
- 会话存储(Session Store):存储用户会话信息,支持分布式会话共享。
- 排行榜/计数器:利用有序集合(Sorted Set)实现实时排名和原子计数。
- 消息队列:通过 List、Stream 等数据结构实现轻量级消息队列和发布订阅。
- 实时数据处理:如实时分析、地理位置服务(GEO)、限流器(Rate Limiter)。
- 分布式锁:利用 SETNX 命令实现跨进程的互斥锁机制。
【深度推导/细节】
缓存场景的典型架构与淘汰策略
- 架构位置:通常部署在应用层与数据库层之间,遵循“先查缓存,未命中再查数据库”的流程。
- 缓存击穿/雪崩/穿透防护:
- 击穿:热点 key 过期瞬间大量请求直达数据库 → 解决方案:设置永不过期或使用互斥锁重建缓存。
- 雪崩:大量 key 同时过期导致请求涌向数据库 → 解决方案:设置随机过期时间或采用高可用集群。
- 穿透:查询不存在的数据 → 解决方案:布隆过滤器(Bloom Filter)拦截非法请求。
- 淘汰策略(8 种,核心 4 种):
- volatile-lru:从已设置过期时间的 key 中淘汰最近最少使用的。
- allkeys-lru:从所有 key 中淘汰最近最少使用的(最常用)。
- volatile-ttl:淘汰即将过期的 key。
- noeviction:不淘汰,内存满时写入操作返回错误(默认策略)。
消息队列的实现演进
- 早期方案(List):
- LPUSH/RPOP 实现简单队列,但需轮询。
- BRPOP 实现阻塞读取,减少空轮询开销。
- 现代方案(Stream,5.0+):
- 支持多消费者组、消息持久化、ACK 确认机制,功能对标专业消息队列。
- 典型命令:XADD 发布消息,XREADGROUP 消费消息。
【关联/对比】
| 场景 | 适用数据结构 | 替代方案对比 |
|---|---|---|
| 缓存 | String, Hash | Memcached(仅缓存,无持久化) |
| 会话存储 | Hash | 数据库存储(慢)、Cookie(不安全) |
| 排行榜 | Sorted Set | 数据库排序(性能差) |
| 消息队列 | Stream, List | Kafka(吞吐量高)、RabbitMQ(功能全) |
| 分布式锁 | String(SETNX) | ZooKeeper(强一致)、数据库锁(性能差) |
Redis vs Memcached:
- Redis 支持持久化、多种数据结构、集群模式;Memcached 纯内存、多线程性能高但功能单一。
- 选择依据:需要丰富数据结构或持久化 → Redis;只需简单键值缓存且内存极大 → Memcached。
『面试官追问』
-
Redis 为什么快?
- 内存操作,无磁盘 I/O 瓶颈。
- 单线程模型避免上下文切换(6.0 后引入多线程 I/O,但核心逻辑仍单线程)。
- 高效数据结构(如跳表、压缩列表)。
- I/O 多路复用(epoll/kqueue)。
-
Redis 持久化如何选择?RDB 和 AOF 的区别?
- RDB:定时快照,文件紧凑、恢复快,但可能丢失最后一次快照后的数据。
- AOF:记录每次写操作,数据完整性高,但文件大、恢复慢。
- 生产建议:通常同时开启,AOF 保证数据安全,RDB 用于备份和快速重启。
-
Redis 集群方案有哪些?
- 主从复制:读写分离,数据备份。
- 哨兵模式(Sentinel):自动故障转移,高可用。
- 集群模式(Cluster):数据分片(16384 个槽),横向扩展,官方推荐方案。
-
Redis 大 Key 和热 Key 问题如何解决?
- 大 Key:拆分(如 Hash 分 field 存储)、压缩、异步删除(UNLINK)。
- 热 Key:本地缓存、多副本(通过客户端或代理分片)、读写分离。
-
Redis 事务与数据库事务有何不同?
- Redis 事务通过 MULTI/EXEC 实现,不具备原子回滚(仅保证命令顺序执行,某条失败不影响后续)。
- 数据库事务满足 ACID,支持回滚;Redis 更偏向“命令批量执行”。
【版本差异】
- 4.0:引入混合持久化、内存碎片整理、异步删除命令(UNLINK)。
- 5.0:引入 Stream 数据类型,强化消息队列能力。
- 6.0:支持多线程 I/O(处理网络读写,核心命令执行仍单线程)、SSL 连接。
- 7.0:Function(脚本优化)、多 AOF 文件、Sharded Pub/Sub。
【直击痛点:关键数字与设计】
- 单线程模型:避免竞争,但 CPU 密集型操作可能阻塞(如 KEYS *)。解决方案:使用 SCAN 迭代。
- 内存淘汰阈值:当内存使用达到
maxmemory时触发淘汰策略。 - 持久化配置:AOF 的
appendfsync选项:always:每个写命令同步刷盘,数据零丢失,性能最低。everysec:每秒同步一次(默认),平衡性能与安全。no:由操作系统决定,性能最高,可能丢失大量数据。
【逻辑复现:缓存击穿解决方案】
Step 1:热点 key 过期,瞬时 10k 请求到达 Redis。 Step 2:Redis 返回 nil,所有请求转向数据库。 Step 3:数据库压力激增,可能崩溃。 解决方案(互斥锁重建):
- 请求 A 发现缓存失效,获取分布式锁(SETNX lock_key)。
- 请求 A 查询数据库并重建缓存,释放锁。
- 其他请求等待锁释放或短暂轮询后直接从新缓存读取。 关键点:锁超时时间设置(避免死锁)、双重检查(获取锁后再次验证缓存)。
总结:Redis 凭借其高性能、丰富数据结构和持久化能力,在缓存、会话、实时计算等场景中成为不可或缺的中间件。选择具体方案时需结合数据特性、一致性要求和集群架构综合考量。