缓存中间件-缓存架构的实现(上)

缓存中间件-缓存架构的实现(上) 前言

一眨眼,2019年就过去了。我希望从按照中间件,分别阐述一些常见的架构问题,以及解决方案。一方面这些问题与解决方案具备一定通用性 。另一方面,也算是面试中常见的问题。

我希望根据自己待过各种规模公司的经验来谈一些看法。

如果是针对大部分小公司的工作或面试,这些问题都稍微留下个印象即可。因为小公司的技术对这些问题并不是很看重,或者说机会用不到(小型公司往往追求产品功能的实现,业务的推进等)。

如果是针对大部分中型公司的工作或面试,希望可以完整地知道这些问题与解决方案。因为在中型公司中,这些问题都或多或少遇到,甚至是需要迫切解决的。

如果是大型公司的话,那么不仅仅需要知道这些问题与解决方案。还需要从中理解为什么会有这样的问题,为什么这样解决,在现有的项目中应该如何应用,是否提升空间等。因为在大公司中,一方面其内部往往采用自研框架,其它框架能够借鉴的只有方案,思想等精髓;另一方面大公司不缺乏那些应用开源框架的人,缺的是把握方案通用思想的人。

如果上述无法理解的话,大家可以从功能性追求与非功能性追求两个方面去思考。就像写一个简单的方法一样,最基本的要求是实现其功能,紧接着就是不断追求其非功能性(如性能,扩展性,安全性等)。放大来看,对于公司的技术发展也是如此,或者说更为严格。

之后找个机会,专门写个博客,来谈谈我对公司技术与公司的看法。

话题收回来,接下来,让我开始有关中间件问题与解决方案的阐述吧。

概述 缓存的认识

既然提及缓存中间件相关的问题及方案,首先就要谈谈这个缓存。

原本我想通过高速缓存举例,但是想了想还是用内存举例子吧。

比如我们现在玩的单机游戏,往往都容量都非常大(几十G,乃至上百G),轻轻松松都超过了电脑内存(16G)。那么很明显电脑在运行游戏时,是不可能将整个游戏文件都放入内存的。但是如果文件都在硬盘里,需要的时候再读取,显然硬盘的读写速度时不够的(由于游戏文件类别很多,所以硬盘不可能一直顺序读写),那游戏也会经常卡顿,加载缓慢等。那么该如何解决这个问题呢?

其实这个问题和我们业务中遇到的一些问题是很类似的。一方面我们希望用户可以在保证用户体验的前提下查询数据(如设备列表,订单列表等),另一方面我们不可能将所有数据都放在内存(内存的读写速度比硬盘快,所以就不解释为什么用硬盘了)中。那么到底该怎么解决这个问题呢?

这里就需要说到局部性原理了。局部性原理指的是数据的访问往往趋向于聚集在较小的连续区域。这里的连续区域包含两个方面:

时间维度:一个被使用的数据,在接下来较短的时间内,往往会被再次使用。

空间维度:一个被使用的数据,其关联的数据,往往也会被使用。

局部性原理是在内存,高速缓存部分,提出来用于解决问题的。

其实,我与朋友交流分布式的一些想法时,经常说:分布式系统和单机内部是非常相似的,很多理念都是相通的。当想通了这点后,就可以去思考两者的区别的。

缓存中间件其实就是利用了局部性原理,不过缓存中间件本身只实现了局部性原理的时间维度。这也是为什么很多人都说缓存中间件是用来保存热点数据,符合二八定律。不过我们可以在应用部分实现局部性原理的空间维度。

缓存的定位

五六年前,有人就提出一个有关缓存的问题,那就是缓存作为一个非持久化数据,我们该怎么划分它。是否需要保证它的可用性。其中就有一位阿里的前辈在他的书中提到,他更倾向于认为缓存并不是一种持久化数据,不该将缓存作为一种可靠数据源。但是这位前辈也表示现有的框架中对缓存依赖较重,应该在一定程度上保护它们,避免缓存雪崩等情况。

我的看法是,在现有的技术体系中,缓存中间件等已经不再只是一个缓存了。一方面我们已经将Session等重要数据放在了缓存中,并且目前没有一个更合适的对应存储(我认为暂时也不需要一个新的存储方式。但是如果需要的话,可以将缓存中间件实例等按照内容的生命周期等进行分组)。另一方面,我们会需要明确缓存在系统中职责,它只是用来作为缓存,以及一些分布式内存。但是诸如单机所有的内部调用,应该通过消息中间件或RPC等来实现。并且明确不同缓存的职责,如Session不该放在Cookie中等。

缓存的分类

缓存框架大致可以从客户端到数据源,分成以下分类。

浏览器缓存

Cookie

LocalStorage

SessionStorage

CDN缓存

负载层缓存

Nginx缓存模块

Squid缓存服务器

Lua扩展

应用层缓存

Etag

ThreadLocal

Guava

外部缓存

Redis

数据库缓存

MySql缓存

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfxfw.html