[TOC] #### 1. 前言 --- 击穿是一个热点 key 出问题 雪崩是一大批 key 同时出问题,或者更惨:Redis 整个挂了,影响面比击穿大得多 #### 2. 两种场景 --- 场景一:大量 key 同时过期 批量导入数据的时候,都设了相同的过期时间: ```bash set key1 value1 EX 3600 set key2 value2 EX 3600 set key3 value3 EX 3600 ``` 3600 秒后,这些 key 同时过期,请求同时打到 MySQL,数据库直接扛不住 场景二:Redis 宕机 整个 Redis 不可用,所有请求全部打到 MySQL,比场景一更严重 #### 3. 解决方案 --- 过期时间加随机值:错开过期时间,避免同时失效,简单有效,一行代码的事 ```bash import random ttl = 3600 + random.randint(0, 300) redis.set(key, value, ex=ttl) ``` 多级缓存:本地缓存 + Redis,即使 Redis 挂了,本地缓存还能扛一阵 Redis 高可用:哨兵模式或 Cluster 模式,Redis 挂了自动切换,不能让 Redis 成为单点故障 限流降级:MySQL 前面加限流,超过阈值直接返回默认值或错误页 + 宁可降级,也不能把数据库打挂,数据库挂了,整个系统就没了 #### 4. 三大缓存问题 --- 穿透 vs 击穿 vs 雪崩 + 穿透:key 不存在,请求直达数据库 + 击穿:一个热点 key 过期,大量请求同时打数据库 + 雪崩:大批 key 同时过期或 Redis 宕机,所有请求打数据库 严重程度:穿透 < 击穿 < 雪崩 #### 5. 本文小结 --- 小总结: + 雪崩:大批 key 同时过期或 Redis 宕机 + 过期时间加随机值,错开失效 + Redis 高可用 + 限流降级 + 多级缓存 + 比击穿更严重,影响面更大