系统架构师学习平台(点击这里进入)
⚡ Redis 核心指南
Redis (Remote Dictionary Server) — 开源、基于 Key-Value 的内存 NoSQL 数据库,常作为 MySQL 前的高速缓存层。
- 🚀 10W+ QPS
- 💾 持久化 RDB/AOF
- 🔐 Redisson 分布式锁
- 📊 面试高频
💡 一句话:Redis = 内存 + 单线程 + I/O多路复用,读写比磁盘快10~100倍,降低DB压力。
📚 一、数据类型 & 经典场景
| 类型 | 特点 | 典型场景 |
|---|---|---|
| String | 字符串/数值,原子增减 | 缓存、计数器、分布式锁(setnx) |
| Hash | 键值对嵌套 (field-value) | 购物车、用户对象存储 |
| List | 双向链表,有序可重复 | 消息队列、最新评论列表 |
| Set | 无序不可重复,集合运算 | 抽奖(spop)、共同好友(sinter) |
| ZSet | 按分数排序,唯一 | 排行榜、延时队列 |
✨ 特殊类型
- 🗺️ Geo
附近的人 / 门店距离 - 📊 HyperLogLog
日活UV统计 (0.81%误差) - 🎯 Bitmap
签到 / 在线状态 / 布隆过滤器基础
⚠️ 二、缓存三兄弟 · 穿透|击穿|雪崩
🔍 缓存穿透
问题:查询不存在的数据,请求绕过缓存直达DB,恶意攻击可能导致DB崩溃。
✅解决方案:① 缓存空对象 (短期TTL);②布隆过滤器(位图+多个hash,高效拦截不存在Key,允许小概率误判)。
💥 缓存击穿 (热点key过期)
问题:高并发下热点key失效,大量请求同时打到数据库。
✅解决方案:① 热点key永不过期(逻辑过期);②互斥锁 (分布式锁),仅允许一个线程重建缓存。
🌊 缓存雪崩
问题:大量key同时过期 或 Redis宕机,瞬时流量压垮数据库。
✅解决方案:① TTL加随机值;② Redis集群高可用;③ 多级缓存;④ 限流/熔断。
📖 记忆口诀:穿透无中生有布隆挡,击穿过期锁与非期扛,雪崩大量过期加随机,三兄弟保底限流强。
🔄 三、缓存与MySQL一致性(双写)
数据变化时保证 Redis 与 DB 最终一致性的常见方案:
| 方案 | 实现方式 | 特点 |
|---|---|---|
| 先更DB + 删缓存 | 更新数据库后删除Redis缓存,读取时重建 | 简单,可能短暂不一致 |
| 延迟双删 | 先删缓存 → 更新DB → 延时再次删除 | 避免旧数据回写,延迟难控制 |
| MQ异步通知 | DB更新后发消息,消费者更新缓存 | 解耦、有重试,最终一致 |
| Canal监听Binlog | 伪装MySQL从库,读取binlog同步到Redis | 无业务侵入,实时性高 |
选型建议:强一致性业务直接查库;允许短暂不一致 → MQ/Canal 最终一致。
💾 四、持久化机制 (数据不丢失)
| 特性 | RDB (快照) | AOF (追加日志) |
|---|---|---|
| 原理 | 定期生成全量二进制快照 dump.rdb | 记录每条写命令到 appendonly.aof |
| 恢复速度 | 快速(直接加载二进制) | 慢(逐条重放命令) |
| 数据安全 | 可能丢失最后一次快照后的数据 | 每秒刷盘最多丢1秒数据 |
| 性能影响 | fork子进程,短暂阻塞 | fsync策略影响IO |
🚀生产最佳实践:混合持久化(RDB全量备份 + AOF增量补充)
配置:appendonly yes+appendfsync everysec+ 合理RDB save规则。
⏳ 五、过期删除 & 内存淘汰
Redis采用:惰性删除 + 定期删除
▪ 惰性删除:访问key时检查过期则删除 → 节省CPU。
▪ 定期删除:每隔100ms随机抽查一批过期key → 平衡CPU与内存。
📌 内存淘汰策略 (达到maxmemory时)
| 策略 | 行为 | 推荐场景 |
|---|---|---|
| volatile-lru | 从设置过期时间的key中淘汰最近最少使用 | 大部分生产场景(有永久数据) |
| allkeys-lru | 从全体key淘汰最近最少使用 | 纯缓存场景,数据可重建 |
| volatile-lfu | 淘汰访问频率最低的(设置过期) | 热点数据倾斜 |
| noeviction | 不淘汰,内存满时写入报错(默认) | 金融/支付强数据安全 |
💡 LRU = 最久未访问,LFU = 最少频率访问(带衰减机制)。
🔒 六、分布式锁(Redisson实现)
场景:集群定时任务、抢券、扣库存 — 保证同一时刻只有一个线程执行。
原生Redis锁:SET lock value NX EX 10+ DEL,存在原子性隐患。
Redisson 改进:
- ✅ Lua脚本保证 setnx+过期时间原子性
- ✅可重入锁(Hash结构存储线程ID+重入次数)
- ✅WatchDog看门狗:自动续期 (每10秒续期一次,避免业务未完成锁释放)
- ✅ 自旋重试机制,提升性能
- ⚠️ 主从切换可能导致锁丢失,强一致性建议用 ZooKeeper 锁
🐕 看门狗核心:锁持有后自动续期,业务完成需手动unlock,高并发下性能优越。
🌐 七、高可用 & 集群进化
📡 主从复制 (读写分离)
一主多从,主写从读。全量同步:首次连接 bgsave + RDB;增量同步:通过偏移量从复制积压缓冲区获取缺失命令。
👁️ 哨兵模式 Sentinel
监控 + 自动故障转移 + 通知客户端。解决主从手动切换。
⚠️ 脑裂问题:配置最少从节点个数和同步延迟阈值缓解。
🧩 分片集群 (Cluster)
解决海量数据+高并发写:
16384个哈希槽,每个key通过CRC16(key)%16384映射到槽,槽分布在多个主节点,水平扩展。
每个主节点可带从节点,自动故障转移。不支持跨槽事务,可用{hash_tag}强制同槽。
💡 生产建议:节点数 ≥ 3,副本数 ≥ 1,避免脑裂。结合哨兵实现高可用,海量数据选用Cluster。
⚡ 八、为什么Redis如此快?
- ✅ 纯内存操作,读写极快
- ✅ 单线程执行命令(6.0后IO多线程但命令仍单线程),避免上下文切换和竞态
- ✅I/O多路复用 (epoll):单线程同时监听多个socket,事件驱动不空转
- ✅ 高效数据结构设计 & 渐进式rehash
🔧 Redis变慢了怎么排查?
- 慢查询日志:
slowlog get查看复杂命令 - 避免bigkey:
--bigkeys扫描,大key阻塞主线程 - 大量key同时过期 → TTL添加随机值
- AOF重写与磁盘竞争:配置
no-appendfsync-on-rewrite yes - 检查swap:
INFO memory,若swap过大则增加内存/集群扩容
📌 九、Redis vs Memcache & 高频考点
| 对比维度 | Memcache | Redis |
|---|---|---|
| 数据类型 | 仅字符串 | 丰富 (String/Hash/List/Set/ZSet等) |
| 持久化 | 不支持,重启丢失 | RDB+AOF混合持久化 |
| 高可用 | 无原生支持 | 主从/哨兵/集群 |
| 原子性 | 部分指令 | 单指令原子 + Lua保证多指令 |
💬 面试高频附加题:
• 数据库有1000w数据,Redis仅缓存20w热点 → 选用allkeys-lru或volatile-lru策略。
• Redis内存满了怎么办?取决于淘汰策略,默认 noeviction 直接报错。
• 布隆过滤器实现原理:位数组 + 多个hash函数,通过0/1快速判断“肯定不存在”,存在微小误判率。
• 缓存三兄弟解决方案汇总:穿透(布隆/空值)、击穿(互斥锁/逻辑过期)、雪崩(随机TTL/集群/限流)。
📖 十、速记汇总·一图流
- 🏆 穿透
布隆过滤器+空值缓存 - 🏆 击穿
互斥锁/逻辑永不过期 - 🏆 雪崩
随机TTL+集群+限流 - 💾 持久化
RDB快照 + AOF everysec - 🔁 淘汰策略
allkeys-lru / volatile-lru - 📈 集群
哨兵(高可用) → Cluster(水平分片)
🔥 总结:Redis基于内存、单线程+I/O多路复用成就高性能;生产环境务必配置合理淘汰策略+持久化,使用Redisson优雅解决分布式锁。
适用场景:缓存、分布式锁、排行榜、计数器、消息队列、Session共享、实时分析。