2026-04-09 04:47:11
定义:缓存雪崩是指在某一个时刻出现大规模的key失效,导致大量的请求直接打在数据库上面,造成数据库压力巨大,甚至可能导致数据库宕机。
问题分析:造成缓存雪崩的关键在于同一时间的大规模key失效,主要原因有两种:Redis宕机和采用了相同的过期时间。
解决方案:
事前:
均匀过期:设置不同的过期时间,让缓存失效的时间尽量均匀,避免大量key同时失效。
分级缓存:设置多级缓存,每一级缓存的失效时间都不同,当第一级缓存失效时,可以访问第二级缓存。
热点数据缓存永远不过期:
物理不过期:针对热点key不设置过期时间。
逻辑过期:把过期时间存在key对应的value里,通过后台异步线程进行缓存的更新。
保证Redis缓存的高可用:使用主从+哨兵或Redis集群来避免Redis全盘崩溃。
事中:
互斥锁:在缓存失效后,通过互斥锁或队列控制读数据写缓存的线程数量,避免大量线程同时访问数据库。
熔断机制:当流量达到一定阈值时,直接返回提示信息,防止过多请求打在数据库上。
事后:
开启Redis持久化机制,尽快恢复缓存数据,一旦重启,能从磁盘上自动加载数据恢复内存中的数据。
定义:缓存击穿是指某个热点的key失效,大并发集中对其进行请求,导致大量请求直接访问数据库,造成数据库压力剧增。
问题分析:关键在于某个热点的key失效,导致大量请求直接打在数据库上。
解决方案:
物理不过期:针对热点key不设置过期时间。
逻辑过期:把过期时间存在key对应的value里,通过后台异步线程进行缓存的更新。
定义:缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致每次请求都直接访问数据库,造成数据库压力过大。
问题分析:关键在于传入的key在Redis中不存在,且在数据库中也不存在。如果有恶意攻击者不断请求不存在的数据,会对数据库造成致命压力。
解决方法:
当出现Redis和数据库都查不到数据的情况时,将这个key保存到Redis中,value设为"null",并设置极短的过期时间。但这种方法对于随机的不存在key无效。
将数据库中的所有key都存储在布隆过滤器中,查询Redis前先去布隆过滤器查询key是否存在,如果不存在就直接返回,避免访问数据库。

如何选择:
定义:在某个Key接收到的访问次数显著高于其它Key时,可以将其称之为HotKey。
问题分析:业务规划不足、Redis不正确的使用、无效数据的堆积、访问突增等都可能产生HotKey。
解决方法:
找出HotKey:
预估热key,如秒杀商品、火爆新闻等。
在客户端或Proxy端进行统计。
利用Redis自带的命令(如monitor、hotkeys,但执行缓慢)或基于大数据领域的流式计算技术进行统计。
处理HotKey:
变分布式缓存为本地缓存:发现热key后,将缓存数据加载到本地缓存中。
在每个Redis主节点上备份热key数据,采用随机读取方式分散访问压力。
利用限流熔断保护措施:对每个系统实例的缓存集群读操作进行限流,超过阈值则熔断。
定义:通常将含有较大数据或含有大量成员、列表数的Key称之为大Key。
问题分析:业务规划不足、Redis不正确的使用、无效数据的堆积、访问突增等都可能产生BigKey。
解决方法:
找出BigKey:
使用redis-cli --bigkeys命令。
获取Redis的rdb文件,通过rdbtools分析。
通过业务层记录Redis访问并异步汇总分析。
处理BigKey:
string类型的big key,尽量不要存入Redis中,或使用文档型数据库MongoDB、CDN等存储。
将大value分拆成多个key-value存储,使用mget获取值。
将hash、set、zset、list中的大量元素分拆存储。
删除大key时不要使用del命令,使用unlink命令进行非阻塞删除。
定义:缓存预热是指系统上线后,提前将相关的缓存数据加载到缓存系统,避免用户请求时先查询数据库再缓存数据。
问题分析:如果不进行预热,Redis初始状态数据为空,系统上线初期高并发流量会直接访问数据库,造成数据库压力。
解决方法: