亿级流量峰值没在怕,“缓存”技术来减压!

博文小编

2021-01-12



许多大型互联网系统,如电商、社交、新闻等App或网站,动辄日活千万甚至上亿,每分钟的峰值流量在数十万以上,架构上如何应对如此高的流量峰值呢?
本文选自《技术人修炼之道:从程序员到百万高管的72项技能》一书,快来了解下如何通过“缓存”技术来给系统减压吧!

流量峰值给系统带来的主要危害在于,它会瞬间产生大量对磁盘数据的读取和搜索,通常数据源是数据库或文件系统,当数据访问次数增大时,过多的磁盘读取可能会最终成为整个系统的性能瓶颈,甚至压垮整个数据库,导致系统卡死、服务不可用等严重后果。
常规的应用系统通常会在需要的时候对数据库进行查找,因此系统的大致结构如下。

当数据量较大时,需要减少对数据库磁盘的读写操作,因此通常都会选择在业务系统和数据库之间加入一层缓存(Cache),从而减少数据库的访问压力,结构如下。

缓存在实际的应用中并非如此简单,下面通过几个比较经典的缓存应用场景来看一些问题。

▊ 缓存和数据库之间的数据一致性问题
常用的缓存处理机制有如下几种。
Cache Aside 模式
种模式通常都先从数据库缓存开始查找,如果缓存没有命中,则从数据库中查找。该模式会发生如下三种情况:
● 缓存命中:当查找的时候发现缓存中存在查找的数据,那么直接从缓存中提取。
● 缓存失效:当缓存中没有数据的时候,则从数据库里面读取源数据,再同步到缓存中。
● 缓存更新:当有新的写操作去修改数据库里面的数据时,需要在写操作完成之后,让缓存里面对应的数据失效,做缓存同步。
Cache Aside模式是在实际应用开发中最常用的模式,但这种模式的缓存处理并不完美。
例如,一个读操作没有命中缓存,然后到数据库中取数据,此时发生一个写操作,在数据库中完成写操作后,让缓存失效,然后之前的读操作再把老的数据放进去,就会出现脏数据。
分布式环境中要想完全保证数据一致性是一件极为困难的事情,只能够尽可能地减少数据不一致性问题。
Read Through模式
指应用程序始终从缓存中请求数据,如果缓存中没有数据,则它负责使用底层提供的程序插件从数据库中检索数据,检索数据后,缓存会自行更新并将数据返回给调用的应用程序。
使用Read Through模式有一个好处,由于总是使用key从缓存中检索数据,调用的应用程序不知道数据库,而由存储方来负责自己的缓存处理,这使得代码更具可读性,更清晰。
但Read Through模式也有相应的缺陷,开发人员需要编写相关的程序插件,增加了开发的难度。
Write Through模式
和Read Through模式类似,当数据进行更新时,先去缓存中进行更新,如果命中,则先更新缓存再由缓存方来更新数据库。如果没有命中,就直接更新缓存里面的数据。
Write Behind Caching模式
这种模式通常先将数据写入缓存,再异步地写入数据库进行数据同步。
这样的设计既可以减少对数据库的直接访问,降低压力,同时对数据库的多次修改可以合并操作,极大地提升了系统的承载能力。
但是使用Write Behind Caching模式处理缓存数据有一定的风险,如当缓存机器出现宕机时,数据有丢失的可能。

▊ 缓存在高并发场景中存在的问题
缓存过期后请求将尝试从后端数据库获取数据,这是一个看似合理的流程。但是,在高并发场景下,有可能多个请求并发地从数据库获取数据,会对后端数据库造成极大的冲击,甚至导致“雪崩”。
此外,当某个缓存key被更新时,也可能被大量请求获取,这也会导致一致性问题。那么如何避免类似问题呢?可以使用类似“锁”的机制,在缓存更新或者过期的情况下,先尝试获取锁,当更新或者从数据库获取完成后再释放锁,其他请求只需要一定的等待时间即可直接从缓存中继续获取数据。
缓存穿透问题
缓存穿透也称为“缓存击穿”。很多朋友对缓存穿透的理解是:由于缓存故障或者缓存过期导致大量请求穿透到后端数据库服务器,从而对数据库造成巨大冲击。
这其实是一种误解。真正的缓存穿透应该是:
高并发场景下,如果某个key被高并发访问,没有命中,出于容错性考虑,会尝试从后端数据库中获取数据,从而导致大量请求到达数据库,而当该key对应的数据本身为空时,就会导致数据库中并发地执行很多不必要的查询操作,从而给数据库带来巨大的冲击和压力。
可以通过如下常用方式来避免缓存穿透问题。

● 缓存空对象
对查询结果为空的对象也进行缓存,如果是集合,则可以缓存一个空的集合(非null),如果是单个对象,则可以通过字段标识来区分。这样可以避免请求穿透到后端数据库,保证缓存数据的时效性。
这种方式实现起来成本较低,比较适合命中率不高但可能被频繁更新的数据。
● 单独过滤处理
对所有对应数据可能为空的key进行统一存放,并在请求前做拦截,可以避免请求穿透到后端数据库。
这种方式实现起来相对复杂,比较适合命中率不高但是更新不频繁的数据。
缓存颠簸问题
也被称为“缓存抖动”,可以看作一种比“雪崩”更轻微的故障,但是也会在一段时间内对系统造成冲击和性能影响,一般是由缓存节点故障导致的。业内推荐的做法是通过一致性Hash算法来解决问题。
缓存的雪崩
由于缓存的原因,导致大量请求到达后端数据库,从而导致数据库崩溃,进而整个系统崩溃,发生灾难。原因有很多种,上文提到的“缓存并发”“缓存穿透”“缓存颠簸”等问题,都可能导致缓存的雪崩。这些问题还可能被恶意攻击者利用。
还有一种情况,例如在某个时间点,系统预加载的缓存周期性地集中失效了,也可能会导致雪崩。为了避免缓存周期性地集中失效,可以通过设置不同的过期时间来错开缓存过期时间。
从应用架构的角度,可以通过限流、降级、熔断等手段来降低缓存雪崩的影响,也可以通过多级缓存来避免这种灾难。
此外,从整个研发体系流程的角度,应该加强压力测试,尽量模拟真实场景,尽早地暴露问题,从而加以防范。
缓存是大型互联网系统架构中常用的一种技术,在设计缓存架构的过程中,要根据业务场景进行有针对性的设计,避免缓存延迟、脏数据、缓存雪崩等问题,提高系统的高可用性和健壮性。
(完)

本文节选自《技术人修炼之道:从程序员到百万高管的72项技能》一书。

▊《技术人修炼之道:从程序员到百万高管的72项技能》
黄哲铿 著

全方位讲解IT技术人技能首著
72项核心技能,突破职业瓶颈实现职场跃迁
本书旨在帮助IT技术人员提升职场核心技能、架构思维、团队管理能力、商业认知,让每一位普通的技术从业者,修炼成为“技术职场超级个体”,通过全面升级个人的底层操作系统,突破瓶颈,实现职场跃迁。

72项核心技能列表

读者评论

相关博文

  • 社区使用反馈专区

    陈晓猛 2016-10-04

    尊敬的博文视点用户您好: 欢迎您访问本站,您在本站点访问过程中遇到任何问题,均可以在本页留言,我们会根据您的意见和建议,对网站进行不断的优化和改进,给您带来更好的访问体验! 同时,您被采纳的意见和建议,管理员也会赠送您相应的积分...

    陈晓猛 2016-10-04
    4221 662 3 6
  • 迎战“双12”!《Unity3D实战核心技术详解》独家预售开启!

    陈晓猛 2016-12-05

    时隔一周,让大家时刻挂念的《Unity3D实战核心技术详解》终于开放预售啦! 这本书不仅满足了很多年轻人的学习欲望,并且与实际开发相结合,能够解决工作中真实遇到的问题。预售期间优惠多多,实在不容错过! Unity 3D实战核心技术详解 ...

    陈晓猛 2016-12-05
    2629 35 0 1
  • czk 2017-07-29
    3958 27 0 1