缓存一致性问题
当数据时效性要求很高时,须要保障缓存中的数据与数据库中的保持一致,而且须要保障缓存节点和正本中的数据也保持一致,不能呈现差别景象。这就比拟依赖缓存的过期和更新策略。个别会在数据产生更改的时,被动更新缓存中的数据或者移除对应的缓存。
缓存并发问题
缓存过期后将尝试从后端数据库获取数据,这是一个看似正当的流程。
然而,在高并发场景下,有可能多个申请并发的去从数据库获取数据,对后端数据库造成极大的冲击,甚至导致“雪崩”景象。
此外,当某个缓存 key 在被更新时,同时也可能被大量申请在获取,这也会导致一致性的问题。那如何防止相似问题呢?咱们会想到相似“锁”的机制,在缓存更新或者过期的状况下,先尝试获取到锁,当更新或者从数据库获取实现后再开释锁,其余的申请只须要就义肯定的等待时间,即可间接从缓存中持续获取数据。
缓存穿透问题
缓存穿透在有些中央也称为“击穿”。很多敌人对缓存穿透的了解是:因为缓存故障或者缓存过期导致大量申请穿透到后端数据库服务器,从而对数据库造成微小冲击。
这其实是一种误会。真正的缓存穿透应该是这样的:
在高并发场景下,如果某一个 key 被高并发拜访,没有被命中,出于对容错性思考,会尝试去从后端数据库中获取,从而导致了大量申请达到数据库,而当该 key 对应的数据自身就是空的状况下,这就导致数据库中并发的去执行了很多不必要的查问操作,从而导致微小冲击和压力。
能够通过上面的几种罕用形式来防止缓存传统问题:
1. 缓存空对象
对查问后果为空的对象也进行缓存,如果是汇合,能够缓存一个空的汇合(非 null),如果是缓存单个对象,能够通过字段标识来辨别。这样防止申请穿透到后端数据库。同时,也须要保障缓存数据的时效性。
这种形式实现起来老本较低,比拟适宜命中不高,但可能被频繁更新的数据。
2. 独自过滤解决
对所有可能对应数据为空的 key 进行对立的寄存,并在申请前做拦挡,这样防止申请穿透到后端数据库。
这种形式实现起来绝对简单,比拟适宜命中不高,然而更新不频繁的数据。
缓存平稳问题
缓存的平稳问题,有些中央可能被成为“缓存抖动”,能够看做是一种比“雪崩”更轻微的故障,然而也会在一段时间内对系统造成冲击和性能影响。个别是因为缓存节点故障导致。业内举荐的做法是通过一致性 Hash 算法来解决。
缓存的雪崩景象
缓存雪崩就是指因为缓存的起因,导致大量申请达到后端数据库,从而导致数据库解体,整个零碎解体,产生劫难。导致这种景象的起因有很多种,下面提到的“缓存并发”,“缓存穿透”,“缓存平稳”等问题,其实都可能会导致缓存雪崩景象产生。
这些问题也可能会被歹意攻击者所利用。还有一种状况,例如某个工夫点内,零碎预加载的缓存周期性集中生效了,也可能会导致雪崩。为了防止这种周期性生效,能够通过设置不同的过期工夫,来错开缓存过期,从而防止缓存集中生效。
从利用架构角度,咱们能够通过限流、降级、熔断等伎俩来升高影响,也能够通过多级缓存来防止这种劫难。
此外,从整个研发体系流程的角度,应该增强压力测试,尽量模仿实在场景,尽早的裸露问题从而防备。
缓存无底洞景象
该问题由 facebook 的工作人员提出的,facebook 在 2010 年左右,memcached 节点就曾经达 3000 个,缓存数千 G 内容。他们发现了一个问题——memcached 连贯频率、效率降落了,于是加 memcached 节点,增加了后,发现因为连贯频率导致的问题,依然存在,并没有恶化,称之为”无底洞景象”。
目前支流的数据库、缓存、Nosql、搜寻中间件等技术栈中,都反对“分片”技术,来满足“高性能、高并发、高可用、可扩大”等要求。有些是在 client 端通过 Hash 取模(或一致性 Hash)将值映射到不同的实例上,有些是在 client 端通过范畴取值的形式映射的。当然,也有些是在服务端进行的。
然而,每一次操作都可能须要和不同节点进行网络通信来实现,实例节点越多,则开销会越大,对性能影响就越大。
次要能够从如下几个方面防止和优化:
1. 数据分布形式
有些业务数据可能适宜 Hash 散布,而有些业务适宜采纳范畴散布,这样可能从肯定水平防止网络 IO 的开销。
2.IO 优化
能够充分利用连接池,NIO 等技术来尽可能升高连贯开销,加强并发连贯能力。
3. 数据拜访形式
一次性获取大的数据集,会比分屡次去获取小数据集的网络 IO 开销更小。
当然,缓存无底洞景象并不常见。在绝大多数的公司里可能基本不会遇到。
据拜访形式 **
一次性获取大的数据集,会比分屡次去获取小数据集的网络 IO 开销更小。
当然,缓存无底洞景象并不常见。在绝大多数的公司里可能基本不会遇到。
对于缓存在高并发场景下的常见问题,你学废了么?