Redis常见缓存问题

Redis常见缓存问题
最新回答
一脸懵

2026-04-09 04:47:11

Redis常见缓存问题一、缓存雪崩

定义:缓存雪崩是指在某一个时刻出现大规模的key失效,导致大量的请求直接打在数据库上面,造成数据库压力巨大,甚至可能导致数据库宕机。

问题分析:造成缓存雪崩的关键在于同一时间的大规模key失效,主要原因有两种:Redis宕机和采用了相同的过期时间。

解决方案:

  • 事前:

    均匀过期:设置不同的过期时间,让缓存失效的时间尽量均匀,避免大量key同时失效。

    分级缓存:设置多级缓存,每一级缓存的失效时间都不同,当第一级缓存失效时,可以访问第二级缓存。

    热点数据缓存永远不过期:

    物理不过期:针对热点key不设置过期时间。

    逻辑过期:把过期时间存在key对应的value里,通过后台异步线程进行缓存的更新。

    保证Redis缓存的高可用:使用主从+哨兵或Redis集群来避免Redis全盘崩溃。

  • 事中:

    互斥锁:在缓存失效后,通过互斥锁或队列控制读数据写缓存的线程数量,避免大量线程同时访问数据库。

    熔断机制:当流量达到一定阈值时,直接返回提示信息,防止过多请求打在数据库上。

  • 事后:

    开启Redis持久化机制,尽快恢复缓存数据,一旦重启,能从磁盘上自动加载数据恢复内存中的数据。

二、缓存击穿

定义:缓存击穿是指某个热点的key失效,大并发集中对其进行请求,导致大量请求直接访问数据库,造成数据库压力剧增。

问题分析:关键在于某个热点的key失效,导致大量请求直接打在数据库上。

解决方案:

  • 互斥锁:在缓存失效后,通过互斥锁或队列控制读数据写缓存的线程数量。
  • 热点数据缓存永远不过期:

    物理不过期:针对热点key不设置过期时间。

    逻辑过期:把过期时间存在key对应的value里,通过后台异步线程进行缓存的更新。

三、缓存穿透

定义:缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致每次请求都直接访问数据库,造成数据库压力过大。

问题分析:关键在于传入的key在Redis中不存在,且在数据库中也不存在。如果有恶意攻击者不断请求不存在的数据,会对数据库造成致命压力。

解决方法:

  • 将无效的key存放进Redis中:

    当出现Redis和数据库都查不到数据的情况时,将这个key保存到Redis中,value设为"null",并设置极短的过期时间。但这种方法对于随机的不存在key无效。

  • 使用布隆过滤器:

    将数据库中的所有key都存储在布隆过滤器中,查询Redis前先去布隆过滤器查询key是否存在,如果不存在就直接返回,避免访问数据库。

如何选择:

  • 对于恶意攻击带来的大量随机key,优先使用布隆过滤器进行过滤。
  • 对于空数据的key有限且重复率高的场景,可以优先采用将无效key存入Redis的方法。
四、HotKey

定义:在某个Key接收到的访问次数显著高于其它Key时,可以将其称之为HotKey。

问题分析:业务规划不足、Redis不正确的使用、无效数据的堆积、访问突增等都可能产生HotKey。

解决方法:

  • 找出HotKey:

    预估热key,如秒杀商品、火爆新闻等。

    在客户端或Proxy端进行统计。

    利用Redis自带的命令(如monitor、hotkeys,但执行缓慢)或基于大数据领域的流式计算技术进行统计。

  • 处理HotKey:

    变分布式缓存为本地缓存:发现热key后,将缓存数据加载到本地缓存中。

    在每个Redis主节点上备份热key数据,采用随机读取方式分散访问压力。

    利用限流熔断保护措施:对每个系统实例的缓存集群读操作进行限流,超过阈值则熔断。

五、BigKey

定义:通常将含有较大数据或含有大量成员、列表数的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初始状态数据为空,系统上线初期高并发流量会直接访问数据库,造成数据库压力。

解决方法:

  • 数据量不大时,工程启动时加载缓存。
  • 数据量大时,设置定时任务脚本刷新缓存。
  • 数据量太大时,优先保证热点数据提前加载到缓存。