03.04 架构学习系列:缓存架构

系统的存储性能,我们可以通过各种手段来提升,但是在些场景下,仅仅提升存储系统的性能已经远远达不到我们的要求了,主要场景有:

需要经过复杂运算后得出的数据,存储系统无能为力读多写少的数据,存储系统有心无力。

这两种场景,想必我们在实际业务中也经常遇到,比如说,我要根据某些特定条件还计算用户的昨日排名,我们如果每次都通过MySQL语句来处理大量数据,那么无论再怎么优化MySQL也无济于事。另外一个,要知道绝大部分的在线业务都是读多写少的,例如一个商品详情页面,如果每一次访问,我们都要去数据库查找一些,即使有索引,也会对MySQL数据库产生非常大的压力。

所以,缓存的出现就是为了弥补存储系统在这些复杂的业务场景下遇到的瓶颈,而缓存的基本原理是将可能重复使用的数据放到内存中,一次生成、多次使用,避免每次使用直接去请求存储系统。

缓存可以给性能带来大幅度的提升,拿Memcache来说,单台Memcache服务器简单的key-Value查询可以达到 TPS 50000以上,其架构如下:

架构学习系列:缓存架构


有利就有弊,缓存虽然大大的减轻了存储系统的压力,但同时也会给架构带来更多的复杂性。而我们则需要针对这些复杂性做出相应的处理,否则,在某些场景下会导致系统直接崩溃。

缓存穿透

什么是缓存穿透?它是指缓存没有发挥作用,业务系统虽然去缓存系统查询数据,但缓存中没有相应数据,业务系统需要再次去存储系统查询数据。

通常存在两种情况:

1、 存储数据确实不存在

这种情况是缓存数据确实不存在。在我们实际应用场景中,如果没有查找某个数据,则不会在缓存中存储相应的数据,这样就会导致在查询时未找到相应数据,每次都去存储系统中再查询一遍,然后再返回数据不存在。所以,在这种情况下,缓存并没有起到分担存储访问压力的作用。

在正常情况下,业务上读取不存在的数据的请求量并不会很大,但是如果有黑客攻击,故意大量访问某些读取不存在数据的业务,还是有可能把存储系统拖垮。所以,我们在实际业务场景中,还需要注意到这方面的问题。至于解决方法,也比较简单,就是如果没有查找到数据,则直接设置一个默认值存在缓存中即可了。

2、缓存数据生成耗费大量时间或资源

这种情况是存储系统中存在数据,但生成缓存数据需要耗费较长的时间或者消耗大量资源,而如果用户在访问时,刚好遇到缓存失效,这时候,访问压力会集中在存储系统上,缓存就不会发挥作用了。

缓存雪崩

缓存雪崩是指当缓存失效或过期后引起系统性能急剧下降的情况。对于高并发的业务系统来说,当缓存失效后,系统需要重新生成缓存,在这期间,可能会接到成百上千的请求,而这些请求都会去请求存储系统,生成新的缓存,从而造成存储系统产生很大的性能压力,更严重的情况下,导致数据库瞬时压力过重雪崩。

缓存雪崩常见的解决方法有两种:更新锁机制和后台更新机制。

一、更新锁机制

对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新,其他的线程要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。

而对于 采用分布式集群的业务,由于服务器过多,即使单台一个线程来更新缓存,几十上百台服务器一起更新也有几个线程,同样会引起雪崩的问题,因此这情况需要用到分布式锁,如Zookeeper。

二、后台更新机制

后台更新,意味着,不再由业务来驱动更新了,而是由后台来更新缓存,这种缓存的有效期为永久有效。后台更新无论是单机多线程还是分布式集群的场景都比较适合,而且相对于更新锁机制要简单一些。

后台更新机制也比较适合刚上线的时候进行缓存预热,将相关的缓存数据直接加载到缓存系统,而不是等到用户访问才来触发缓存加载。

缓存热点

缓存系统本身性能比较高,但对于一些热点的数据来说,如果大量业务请求命中同一份缓存数据,那么缓存服务器的压力也会很大。

缓存热点的解决方案就是复制多份缓存副本,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器的压力。但这里需要注意的是,不能将所有的缓存副本设置统一的过期时间,否则在同时失效到生成缓存的期间,可能 会引发雪崩效应。

缓存是实现业务场景中是经常遇到的,对于高并发业务来说,更为重要,但是需要明白的是,对于缓存根据实际情况来运用,虽然缓存带来了性能的可观提升,如果我们随意应用,维护也是一种成本 ,反而提升了系统的复杂性。


声明:本系列学习内容来自于《从零开始学架构》。另,图片源于网络,若有侵权,请及时联系删除。


分享到:


相關文章: