Redis的缓存更新策略

1.定期生成:

核心逻辑:

按照固定的时间间隔(比如每个小时,每天)批量生成或者更新缓存,而非依赖实时数据变更触发。

实现方式:

定期任务触发:

写一套离线流程(使用shell,python写脚本代码),然后定期缓存更新。

全量/增量更新:

全量:每次生成所有的缓存数据,覆盖原来的数据。

增量:仅更新上次更新后发生变化的缓存数据。

优点和缺点:

优点:实现简单,过程可控,方便排查问题。

缺点:实时性差,因为是定期更新,会有无效更新的情况,比如缓存数据没有变化还是会更新。

2.实时生成:

核心逻辑:

数据一旦发生变化(数据库更新),缓存数据就会更新或者失效,确保了缓存和数据源的一致性。

一段时间后,redis的key都会是一些热点数据。这样不停地写会导致redis的内存占用越来越多。(逐渐达到内存上限,不一定是机器内存上限,可能是redis配置的内存上限)

然后就有了内存淘汰策略。(经典面试题)

内存淘汰策略:

FIFO(First In First Out)先进先出:

把缓存中存在时间最久的(也就是先来的数据)淘汰掉。

LRU(Least Recently Userd)淘汰最久未使用的:

记录每个key最近访问的时间,把最近访问时间最久 的key淘汰掉。

LFU(Least Frequently Userd)淘汰访问次数最少的:

记录每个key最近一段时间的访问次数,把访问次数最少的淘汰掉。

Random随机淘汰:

从所有的key中随机抽取进行淘汰。

缓存预热:

服务启动或者缓存重新启动时,缓存中可能没有数据,此时所有用户请求会直接穿透到数据库。

数据库可能因为瞬间高并发导致被压垮(特别是一些量大的系统)。

用户体验极差(请求响应时间从毫秒级到秒级别)

缓存预热是通过"提前在缓存中加载一些热点数据",让服务启动后缓存命中率迅速提高,数据库承担的请求压力就会变小。

缓存穿透:

缓存穿透是指:查询某个key时,这个key既没有在redis中,也没有在MySQL中,导致每次请求都会直接穿透缓存,直接访问数据库,如果查询大量这样的key(如黑客的恶意攻击),就会导致数据库压力骤增,甚至导致数据库宕机。

缓存穿透的核心原因:

1.业务逻辑导致无效请求:比如代码中缺少参数校验环节,到时非法的key也能进行查询。

2.黑客的恶意攻击。

3.比如运维和开发误操作:不小心把部分数据从数据库中删除了。

缓存穿透的解决方案:

方案一:缓存空值:

当我们查询一个key时,这个key如果在redis和mysql中都不存在,那么就把它存入redis中并设置一个ttl(过期时间),value设为null。后续相同的请求就会返回null,无需访问数据库。

**优点:**实现简单,无需外部依赖,可以快速拦截非法请求。

缺点:

1.占用缓存空间。(大量空的key会浪费内存)

2.在ttl时间内,如果当前key重新存在了,但仍然返回null,那么就需要等到ttl到了,才能继续设置。(比如商品下架但是又上架了);解决方法:可以ttl为5-30s(平衡内存使用和数据实时性),还可以给空值key加上一个特定的前缀。

方法二:布隆过滤器:

在缓存前加一个布隆过滤器,提前过滤"一定不存在的数据",布隆过滤器是一种空间效率极高的概率性数据结构,能判断一个key是否可能存在于数据源中(存在误判,但不存在漏判)

实现步骤:

需要提前初始化布隆过滤器:将数据中有效的数据key提前导入到布隆过滤器中。

拦截请求:先要通过布隆过滤器,如果布隆过滤器判断这个key不存在,直接返回空结果,不会访问缓存和数据库;但是布隆过滤器判断这个key可能存在,就需要再次访问缓存和数据库。

**优点:**内存占用率极低,查询速度也很快

**缺点:**存在误判,当新增数据时,需要更新布隆过滤器,实现难度较大。

缓存雪崩:

缓存雪崩:在某一时刻,Redis中大量缓存的key同时过期或者Redis集群整体不可用,导致缓存的命中率陡然下降,数据库的压力陡然上升,甚至直接宕机。

核心原因:

1.大量的key同时过期。因为设置了相同的过期时间。一旦到期会同时失效,请求全部打向数据库。

2.Redis的集群故障:因网络中断、服务器宕机、内存耗尽等原因,Redis 集群整体不可用,所有请求被迫直接访问数据库。

解决方案:

1.避免key集中过期,为缓存key设置随机过期时间(base_ttl+random(0-300ms)),避免集中过期。

2.部署哨兵+主从模式,确保单点故障后自动切换。

3.服务降级和熔断:当数据库压力超过阈值时,暂时拒绝部分请求(返回空或者返回错误提示)

4.多级缓存兜底:增加本地缓存,作为Redis的二级缓存,减少数据库访问。

缓存击穿:

缓存击穿:某一个热点的key突然过期了,恰好有大量并发请求访问这个key,导致所有请求穿透到数据库,导致数据库压力骤增,甚至宕机。

解决办法:

1.基于统计的方式,设置热点key永不过期。

2.当缓存未命中时,先尝试获取分布式锁,然后只有获取到锁的请求才能查询数据库,其他请求等待重试,限制同时请求数据库的并发数。

3.提前预热+扩咱过期时间。

相关推荐
野犬寒鸦7 小时前
从零起步学习Redis || 第十一章:主从切换时的哨兵机制如何实现及项目实战
java·服务器·数据库·redis·后端·缓存
callJJ10 小时前
缓存雪崩、击穿、穿透是什么与解决方案
缓存
如竟没有火炬12 小时前
LRU缓存——双向链表+哈希表
数据结构·python·算法·leetcode·链表·缓存
阿湯哥12 小时前
Redis数据库隔离业务缓存对查询性能的影响分析
数据库·redis·缓存
麦兜*12 小时前
Redis 7.2 新特性实战:Client-Side Caching(客户端缓存)如何大幅降低延迟?
数据库·spring boot·redis·spring·spring cloud·缓存·tomcat
he___H14 小时前
尚庭公寓中Redis的使用
数据库·redis·缓存·尚庭公寓
不良人天码星1 天前
redis-zset数据类型的常见指令(sorted set)
数据库·redis·缓存
Lisonseekpan1 天前
Java Caffeine 高性能缓存库详解与使用案例
java·后端·spring·缓存
沐浴露z1 天前
分布式场景下防止【缓存击穿】的不同方案
redis·分布式·缓存·redission