Redis缓存异常的解决方案如下:
缓存雪崩
当大量缓存数据同时过期,导致请求直接落到数据库,引发数据库压力骤增甚至崩溃。
- 解决方案1:随机化过期时间
为缓存数据设置随机的过期时间,避免同一时间点大量数据失效。例如,在基础过期时间上增加随机偏移量(如±5分钟),分散失效时间。 - 解决方案2:加锁排队
在并发量可控时,通过加锁机制限制同一时间对数据库的请求数量。例如,使用分布式锁(如Redlock)确保同一缓存键的更新操作串行化。 - 解决方案3:缓存标记与主动更新
为缓存数据增加失效标记,当标记失效时,触发后台任务异步更新缓存,而非直接查询数据库。例如,使用“双缓存”策略,主缓存失效时先检查次缓存。
缓存穿透
请求的键在缓存和数据库中均不存在,导致大量无效请求直接穿透至数据库。
- 解决方案1:接口层校验
在请求入口增加基础校验(如用户鉴权、参数合法性检查),拦截非法请求。例如,对ID≤0的请求直接返回错误。 - 解决方案2:缓存空值
对数据库中不存在的键,缓存一个短期有效的空值(如key-null,TTL=30秒),防止重复查询。需注意设置合理过期时间,避免正常数据被误拦截。 - 解决方案3:布隆过滤器
使用布隆过滤器预判键是否存在。通过多哈希函数将键映射到位图中,若过滤器判定键不存在,则直接返回,避免数据库查询。布隆过滤器存在误判率(可能将不存在的键误判为存在),但空间效率极高,适合大数据量场景。
缓存击穿
热点数据的缓存过期时,大量并发请求同时访问数据库,导致瞬时压力激增。
- 解决方案1:热点数据永不过期
对核心热点数据(如促销商品信息)设置逻辑上的“永不过期”,通过后台任务定期刷新缓存内容而非依赖TTL。 - 解决方案2:互斥锁更新
当缓存失效时,仅允许一个线程查询数据库并更新缓存,其他线程等待或返回旧值。例如,使用Redis的SETNX命令实现分布式锁。
缓存预热
系统上线前或低峰期,提前将热点数据加载至缓存,避免用户首次请求时触发数据库查询。
- 解决方案1:手动刷新
通过管理界面或脚本在上线时手动触发缓存加载。 - 解决方案2:启动自动加载
项目启动时,通过初始化脚本加载关键数据(如配置信息、基础字典)。 - 解决方案3:定时任务刷新
使用定时任务(如Spring的@Scheduled)定期更新缓存,确保数据时效性。
缓存降级
当服务异常或访问量过大时,通过牺牲非核心功能保证核心服务可用性。
- 解决方案1:自动降级
根据系统指标(如响应时间、错误率)自动触发降级策略。例如,当数据库连接池耗尽时,直接返回默认值或缓存的旧数据。 - 解决方案2:人工降级
通过配置开关手动关闭非核心功能(如日志记录、统计报表),释放资源。
降级前需梳理服务依赖关系,明确哪些功能可降级(如商品推荐),哪些必须保证(如支付结算)。
缓存热点Key问题
热点Key过期时,大量并发请求同时触发数据库查询和缓存更新,导致数据库压力激增。
- 解决方案:分布式锁控制
对热点Key的查询加锁,仅允许一个线程查询数据库并更新缓存,其他线程等待或返回旧值。例如,使用Redis的Redlock算法实现分布式锁。