缓存雪崩
-
定义:缓存雪崩是指在某个时间段内,缓存中的大量数据同时失效或者大量的请求集中到某一个时间点发生,导致数据库压力骤增,甚至引起服务崩溃的现象。
-
原因:通常是由于缓存中的大量数据同时过期或者大量的请求集中到某一时间点。例如,如果缓存中的大量数据在同一时间点过期,那么在数据重新加载到缓存之前,所有请求都会直接打到数据库,导致数据库压力骤增。还有一种情况就是缓存中间件宕机。
-
解决方法:可以采取多种方式来缓解缓存雪崩的影响,例如设置不同的缓存过期时间、使用缓存预热、采用滑动过期时间等。
缓存穿透
-
定义:缓存穿透是指恶意请求或者无效请求直接绕过缓存访问数据库,导致数据库压力过大,甚至造成服务宕机的现象。
-
原因:通常是由于缓存中不存在的数据被请求,而且这些请求都直接绕过了缓存,直接查询数据库。如果攻击者通过构造恶意请求来访问不存在的数据,就可能触发缓存穿透。
-
解决方法:可以采取多种方式来防止缓存穿透,例如使用布隆过滤器过滤无效请求、在缓存中预先存储空对象(缓存空值)、设置短期内的黑名单等。
缓存击穿
-
定义:
-
缓存击穿是指一个非常热点的数据,在某个时间点过期了,此时大量的请求同时过来,这些请求发现缓存中没有数据,于是全部去访问数据库,导致数据库压力瞬间增大。
-
-
举例:
-
比如一个热门商品的库存查询接口,在高并发情况下,这个商品的缓存数据刚好过期,瞬间大量的请求直接打到数据库上,可能导致数据库崩溃。
-
-
解决方案:
-
设置热点数据永不过期。
-
加互斥锁,当发现缓存过期时,只有一个线程去查询数据库并更新缓存,其他线程等待。
-
完整些
背景:在实际应用场景中,我们会在程序和数据库之间增加一个缓存层,用来提高数据检索的效率,同时降低数据库的并发压力。
定义:缓存击穿其实就是缓存层没有起到流量缓冲作用,请求因为某些原因全部打到了数据库中。
原因:我认为主要有两种情况导致:主要针对是否存在键。如果说存在键,在键过期的瞬间,有大量的请求进来,直接打到了数据库中。不存在键,也就是大量不存在key的请求,由于访问的key不存在,导致数据本身不存在。
总结:总之在使用Redis承担流量缓冲作用时,需要考虑失效时导致并发压力过大对后端存储设备造成冲击的问题
解决:
-
首先可以对热点数据不设置过期时间,或者在每次访问时更新过期时间,来保证每次对热点数据的访问都能在缓冲区找到。
-
其次可以对访问量较高的数据设置多级缓存数据,尽量减小后端存储设备的压力。
-
还可以使用分布式锁,在缓存失效时,先去获取分布式锁,在从数据库中查找数据,写回缓存中,后续没有获得锁的线程只能等待和重试就行了,虽然该方案牺牲了一定的性能,但可以有效的保护数据库避免被压垮。
-
对于恶意攻击类的场景,可以使用布隆过滤器,应用启动的时候把存在的数据缓存到布隆过滤器中,每次请求先经过布隆过滤器,若不存在,这说明数据一定没有在数据库中,没必要访问数据库。
缓存预热
-
定义:
-
在系统启动或者新的缓存节点加入时,提前将一些可能被频繁访问的数据加载到缓存中,以避免在系统运行初期用户请求时频繁访问数据库,从而提高系统的响应速度和性能。
-
-
大白话理解:
-
就好比你要开一家商店,在正式营业前,你先把一些热门商品摆到货架上(把热门数据放到缓存里),这样等顾客(用户请求)来的时候,就能很快地拿到商品(数据),而不用等你从仓库(数据库)里去取货,节省时间,提高顾客的满意度。
-
缓存更新
-
定义:
-
当缓存中的数据发生变化时,需要及时更新缓存中的数据,以保证缓存中的数据与数据库中的数据一致。缓存更新可以通过主动更新或者被动更新的方式实现。
-
-
大白话理解:
-
假设你的商店里的商品价格发生了变化(数据库中的数据变化了),你就得把货架上(缓存里)的商品价格标签也换一下,这样顾客看到的价格才是正确的。主动更新就是你自己主动去检查商品价格有没有变化,然后更新标签;被动更新就是等顾客发现价格不对告诉你了,你再去更新。
-
缓存降级
-
定义:
-
当系统面临高并发、高负载或者出现故障时,为了保证核心功能的可用性,暂时降低非核心功能的服务质量或者关闭一些不太重要的功能,将原本需要从缓存中获取的数据改为直接从数据库或者其他数据源获取,或者返回一些默认值、旧数据等。
-
-
大白话理解:
-
就像你的商店在高峰期的时候,人特别多,货架上的一些不太热门的商品来不及补货(缓存数据无法获取),这时候你就告诉顾客这些商品暂时没货,让他们先买其他热门商品(保证核心功能可用)。或者你直接拿一些旧的商品给顾客看(返回旧数据),等不那么忙的时候再去整理货架(恢复缓存数据)。
-