likes
comments
collection
share

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(存穿透、缓存击穿和缓存雪崩)

作者站长头像
站长
· 阅读数 22

常见概念

在使用缓存之前,了解缓存领域中的常用术语很重要:

  • 1)缓存命中:表示可以从缓存获取数据,无需再次请求源数据;
  • 2)缓存未命中:表示无法从缓存中获取数据,如果缓存有空间,将会将数据加入缓存;
  • 3)存储成本:当缓存未命中时,需要从源数据中获取并存储到缓存中,这个过程所需的时间和空间称为存储成本;
  • 4)缓存失效:当源数据发生变化时,缓存中的数据变得无效;
  • 5)缓存污染:将不常访问的数据存放在缓存中,导致常访问的数据无法放入缓存;
  • 6)替换策略:当缓存空间不足时,需要替换一些数据。选择替换哪些数据由替换策略决定。常见的替换策略包括:

缓存策略

当涉及到缓存策略时,以下是对三种常见的缓存策略机制进行分析:

Least-Recently-Used (LRU):最近最少使用

LRU是一种基于使用频率的缓存替换策略。它的基本思想是,如果一个数据项最近被访问过,那么它在未来也可能会被频繁访问。因此,当缓存空间不足时,LRU会选择最近最久未被使用的数据项进行替换。

实现LRU策略的一种方法是使用一个双向链表来维护所有缓存的顺序,其中最近使用过的缓存项会被移到链表的前面。当需要替换时,可以从链表的末尾删除最久未使用的缓存项。

Least-Frequently-Used (LFU):最少使用频率

LFU是一种基于使用频率的缓存替换策略。它的基本思想是,如果一个数据项在过去使用频率较低,那么在未来也可能很少被使用。因此,当缓存空间不足时,LFU会选择使用频率最低的数据项进行替换。

实现LFU策略需要维护每个缓存项被访问的频率信息。当某个缓存项被访问时,其对应的频率会增加。当需要替换时,可以选择频率最低的缓存项进行替换。

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

FIFO是一种简单的缓存替换策略。它的基本原则是,最先进入缓存的数据项最先被替换。当缓存空间不足时,FIFO会选择最早添加到缓存中的数据项进行替换。

实现FIFO策略可以使用一个队列来维护缓存项的顺序,新加入的项会被添加到队列的末尾。当需要替换时,可以从队列的头部删除最早添加的缓存项。

需要注意的是,每种缓存策略都有其优点和缺点,适用于不同的应用场景。选择合适的缓存策略取决于资源的特点以及访问模式的情况。例如,如果某个应用具有明显的访问热点,那么LRU可能是一个更好的选择;如果应用中的数据访问频率非常不均匀,LFU可能是一个更好的选择。

策略总结

由于存储空间有限,替代策略的核心问题是如何保留高频访问的缓存数据,以提高缓存命中率和整体缓存效率。难点在于需要通过对数据的历史访问情况进行分析,以预测未来访问情况,并找到合适的策略


缓存访问场景分析

通常,使用缓存的操作如下:请求首先访问缓存数据,如果缓存中不存在,则将会从数据库获取数据,并将其写入缓存;如果缓存中存在数据,则直接返回。 【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(存穿透、缓存击穿和缓存雪崩) 缓存层作为数据访问的前置环节,在高并发情况下可以减轻数据库的负担,降低系统故障的风险。因此,在使用缓存时需谨慎分析。在访问缓存数据时。

缓存处理的三种问题场景

常见的有以下三种场景:缓存穿透、缓存击穿和缓存雪崩。 【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(存穿透、缓存击穿和缓存雪崩)

缓存穿透

每次请求都无法在缓存中找到相应的数据,导致请求直接回源到数据库中,给数据库带来巨大的访问压力,甚至可能导致数据库宕机的现象

原因

请求的数据根本不存在于缓存中,也是说当前访问数据永远不会写入缓存中。但恶意请求或者异常情况下持续发送这样的请求,导致缓存一直未命中,就相当于缓存层形同虚设,从而对数据库造成了巨大的访问压力

措施

为了解决缓存穿透问题,可以采取以下几种措施:

  1. 布隆过滤器(Bloom Filter):采用bloom filter保存缓存过的key,因此可以快速判断请求的数据是否在缓存中,如果不在则可以直接过滤掉,避免对数据库的访问。

  2. 缓存空值缓存:对于一些经常查询但是数据库中不存在的数据,可以将其在缓存中缓存为空值,这样当再次请求时可以直接命中缓存,避免了回源到数据库的操作,设置较短的失效时间。

  3. 异常数据屏蔽:对于恶意请求或者异常情况下的请求,可以针对性地进行限流或者屏蔽,避免对数据库的过度访问。此外还可以针对业务场景对请求的参数进行有效性校验,防止非法请求击垮db。

综上所述,解决缓存穿透问题需要采取合适的技术手段,从而降低对数据库的访问压力,提高系统的稳定性和性能。

缓存击穿

某个热点数据的缓存失效时,大量并发请求直接访问数据库,导致数据库压力剧增,甚至造成存储层的崩溃现象

原因

为了保证缓存数据的时效性,通常会设置一个失效时间,如果是热点key,高并发时会有海量请求直接越过缓存层到数据库,这样就会给数据库造成的负担增大,设置宕机。

场景

  • 缓存失效:当某个热点数据的缓存过期或者被意外删除时,新来的请求无法命中缓存,需要直接访问数据库获取数据,造成大量请求到db层,击垮存储层。

  • 高并发请求:大量的并发请求同一时刻涌入,都请求缓存中已失效的热点数据,导致数据库负载骤增。

措施

  • 互斥锁(Mutex Lock) :在缓存失效时,只允许一个线程(一般是第一个到达的线程)去查询数据库,其他线程等待查询结果并从缓存中获取数据。

  • 热点数据预加载:针对可能会发生缓存击穿的热点数据,可以通过定时任务或者异步加载的方式,在缓存失效前提前将数据加载到缓存中,避免了缓存失效瞬间的高并发请求。

  • 限流策略:对于大量并发的请求,可以通过限流策略来控制并发数量,避免所有请求同时涌入数据库。

  • 使用备份机制:在缓存失效时,可以通过备份机制从数据库中获取数据,并将数据存储到缓存中,避免大量请求直接击穿到数据库。

  • 缓存数据“永远不过期”:如果缓存数据不设置失效时间的话,就不会存在热点key过期造成了大量请求到数据库。但是,缓存数据就变成“静态数据”,因此当缓存数据快要过期时,采用异步线程的方式提前进行更新缓存数据。

通过以上措施的组合,可以有效地解决缓存击穿问题,降低数据库压力,提高系统的稳定性和性能


缓存雪崩

在某一时刻,缓存中的多个key同时失效,导致大量的请求直接访问存储层(如数据库),从而造成数据库负担过重,甚至导致数据库宕机的情况

原因

造成缓存雪崩的主要原因包括:

  • 缓存失效时间设置不合理:如果缓存中的多个key的失效时间相同或者非常接近,那么它们很可能在同一时刻失效,导致大量的请求涌入存储层。

  • 数据库宕机或网络故障:如果数据库出现宕机或者网络故障,此时缓存中的数据已经失效,无法及时从数据库中获取新的数据,从而导致大量请求直接访问数据库。

措施

解决缓存雪崩问题的核心原则是让多个key的失效时间分布更加均匀,避免集体失效的情况。可以采取以下措施:

  • 设置合理的缓存失效时间:将缓存中的多个key的失效时间分散开,避免同时失效。可以使用随机值来设置失效时间,或者在失效时间上加入一些随机因素,使得失效时间分布更加均匀。

  • 使用分布式缓存:将缓存数据分散存储在多个节点上,避免单点故障。当其中某个节点或者一部分节点出现问题时,其他节点可以继续提供服务。

  • 数据预热:在高峰期到来之前,提前将热点数据加载到缓存中,避免在高峰期瞬时失效导致大量请求涌入存储层。

  • 数据更新策略:在更新数据时,采取合适的策略,如异步更新、缓存和数据库同时更新等,避免在缓存失效时对数据库造成瞬时压力。

  • 限流策略:对请求进行限流,控制并发访问数据库的数量,避免系统负荷过大。

综合以上措施,可以有效地减轻缓存雪崩带来的问题,提高系统的稳定性和可靠性。

总结

缓存穿透、缓存击穿和缓存雪崩是三个常见的缓存问题,容易混淆。下面是它们的简要总结:

  • 缓存穿透:指的是请求访问不存在于缓存中的数据,而直接查询存储层(如数据库),这可能是攻击者利用业务漏洞攻击系统。解决方案的核心是过滤非法业务请求,与数据是否热点、缓存失效时间等因素无关。

  • 缓存击穿:指的是热点数据的缓存失效,导致大量请求直接访问存储层(如数据库),造成数据库压力过大的问题。解决方案的核心是避免数据库的并发操作。

  • 缓存雪崩:指的是多个缓存 key 同时失效,不一定与数据是否热点有关。解决方案的核心是让缓存 key 的失效时间分布更均匀,避免集体失效的情况。

要解决这些问题,可以采取相应的措施,例如进行合理缓存设置、使用互斥锁、热点数据预加载、限流策略等。通过综合应用这些解决方案,可以提高系统的性能、稳定性,避免缓存问题引发的系统崩溃或过载。

转载自:https://juejin.cn/post/7251490984135409721
评论
请登录