1 漫谈缓存 - 缓存概述
前言
在股市动荡,投资乏力时你可能听过现金为王;在传统媒体互联化的潮流中,你可能听过流量为王;在网络知识内容越来越同质的时代,你可能听过内容为王。那么在你系统性能表现不佳,客户抱怨响应时间过长等问题中,我想告诉你的是缓存为王。如果你是个爱吃小龙虾的,那么很多事情没有什么是一顿小龙虾搞不定的,如果搞不定,那就两顿。同理,不管什么系统,位于系统的哪一层,没有什么是缓存解决不了的,如果解决不了那就加一层。
什么是缓存
言归正传,我们来正式谈一谈缓存。我们不要以为经常听到,看到,用到的东西,就一定对其了解。要知道万有引力发现也是从苹果为什么从树上掉下来这么司空见惯的现象中来的。
缓存和缓冲
缓存和缓冲有什么区别?相信很多人其实对这两个词解释不清楚,甚至混用。从英文的角度去看缓存是cache,缓冲是buffer,它们是完全不同的两个单词。
我曾看到有的人是这么解释缓存的:位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构。
我觉得这个概念其实更适合缓冲。为什么呢?缓存和缓冲从中文的角度看,仅一字之差,关键性区别就在这一个字。
缓存的侧重点是存,作用是提供一种便利性。比如:我们去超市里买东西,为了增加我们购物的便利性,超市会在购物入口提供一个寄存箱,用来存放我们随身携带的一些大件物品;还有我们经常使用的丰巣快递柜,无论收寄快递,我们只要前往我们住所或上班地点较近的丰巣快递柜进行相应的操作的就行了,丰巣的快递柜为我们寄取物品提供了很好的便利性。
缓冲的侧重点是冲,它的目的是让对象冲的慢点,作用是提供一种保护性。比如:在公路上,在转弯下坡和小区路口的路段,都会建造一个减速带,用来强行对车子减速,免得车子速度过快产生危险;其实我们平时用的很多东西都有缓冲装置:自行车座位下面的减震垫、一些篮球鞋的鞋垫、运动员跳高竿下面垫子等等物品提供的都是缓冲功能,都是对我们身体部位的保护。
我们再回头看之前的那个解释,大家是不是觉得这个解释更适合缓冲了?所以我更喜欢这么去理解这两个词的概念。
缓存cache:为了提供便利性,建立的数据交换区。
缓冲buffer:为了提供保护性,建立的数据交换区。
计算机缓存
就拿我们熟悉的计算机CPU来举例,看看缓存的作用。
CPU由两大部件组成:控制器和运算器,控制器用来处理指令;运算器用来进行实际运算。
一般我们的数据都会从硬盘上加载到内存中,再由cpu去内存当中去取数据。但是我们看看cpu的频率和内存频率有多大区别。
我们通常衡量一个CPU好坏的指标是其频率,比如4.0GHz,表示一秒钟内这个CPU可以进行4亿次运算,每次运算时间为0.25纳秒。
那么我们去访问内存数据的时间大约是上百纳秒,二者相差百倍。
为了充分利用CPU的高效性,我们引入了多级缓存机制,来增加CPU取数据的便利性。所以一般CPU中会包含一级缓存、二级缓存,甚至有的还有三级缓存。每种缓存的材料都有不同,越是靠近CPU的材料越接近CPU,频率相差越少。
所以通过CPU多级缓存,我们在取数上从二方面增加了便利性,一方面是距离上便利性,本来CPU和内存物理距离上本来就远,而多级缓存更近(类似之前丰巣快递柜);另一方面是时间便利性,由于缓存本身频率更快,取数据的时间更短了。
大多数CPU计算的时候有80-90%的数据是从缓存中直接取得的,使得我们的计算机运行效率大大得到提升。
下图是一个CPU多级缓存的简易示意图:
软件设计Buffer困惑
写过JAVA的人都知道,在JAVA传统的BIO操作里,有很多的流操作,这些输入输出流都是基于抽象基类InputStream/OutputStream。其中有一个缓冲流BufferedxxxStream,相信很多人都用过。但是我碰到过的很多开发人员却把这个流理解成了缓存,因为用了这个流,文件I/O操作的效率比不用之前提升了不少。但是我们可以清楚的看到官方的把它叫做缓冲流,名字也是Buffer打头的。好像也没提供啥保护性,好像你讲的不对哦,这个缓冲提供的明显是便利性,真的是这样吗?
我们想想看,为什么BufferedxxxStream叫缓冲?如果不用它的话,我们是不是要频繁的和硬盘进行I/O操作,有了缓冲流,相当于减少了和I/O的频繁操作次数,就像本来每秒要交互1000次,现在减少到了1次。是不是对硬盘或系统起到了保护性作用?缓冲流正是起到了I/O慢点冲的作用。至于效率上的提升,真是因为次数上的减少,原来的999次对硬盘的操作,变成了对内存的操作。要知道磁盘搜索时间是毫秒级别的,和内存相比,效率相差十万百万倍,所以这才是缓冲流效率提升的真相。
从整体角度看缓存
其实缓存思想在我们计算机或者软件设计上随处可见应用十分广泛。接下来我们看看缓存的分类。
缓存分类
其实目前业界并没有严格的缓存分类,都是根据其实际的应用场景进行分类。
如果按照硬件和软件来分,就可以分成:硬件缓存和软件缓存。
如果按照一个对象类型上可以分为:客户端缓存、服务端缓存、第三方缓存。
如果按照缓存资源类型可以分为:静态缓存和动态缓存。
如果按照缓存的位置可以分为:本地缓存、分布式缓存。
如果按照系统架构上可以分为:web端缓存、应用端缓存、数据库缓存等。
本文不可能穷尽所有的分类方式,也不能面面俱到介绍锁列出的各种缓存类别。作为一个软件开发人员或者架构师,那最常见的方式还是从系统架构作为第一划分维度去了解和掌握缓存,是最直接最有效的。在第一维度的划分下,我们还可以根据第二和第三维度进一步细化。
接下来我们就从系统架构角度来看一看缓存。
系统架构角度看缓存
架构从粗的大方向可以分为三层:WEB层,应用层,持久层。
现代软件设计发展较快,层次也越分越细,但是只是根据功能职责进一步对这三层进行了更细粒度的划分,比如:界面层,控制层,业务层,服务层,代理层,数据层。就是把之前的每层根据功能职责都划分出了二层,就拿原本的应用层来说,划分成了业务层和服务层。业务层可能会对业务的热点数据进行缓存,服务层主要是把一些公共的功能集中起来以SOA或者微服务的方式封装好,以API方式提供,不需要缓存,增大了整个系统的可扩展性。
根据这三层作为第一维度的划分,整理除了下面的表格:
缓存对象是指该层主要缓存的是哪些数据,缓存方式是指一般我们会采用什么手段去缓存这些缓存对象,常用技术工具就是各种缓存方式目前比较流行的一些技术与工具了。
缓存的重要指标
我们现在知道,缓存的主要目的是提供便利性。如果你家小区明明有丰巣快递柜,但是要收很高的费用,快递员每次要你到小区门口来拿快递,那这个快递柜(缓存)的意义就没有了。那么软件设计上的缓存也一样,我们要考查这个缓存是不是真的提供了便利性。那怎么衡量呢?我们是通过缓存的命中率来衡量的,说白了就是你去缓存里拿你要的东西能不能拿到。
缓存的问题
这里主要是想和大家说一下,再好的东西,也要我们合理的去利用。一个好的系统缓存需要我们精心去设计,一般的缓存设计会存在这么二个问题:缓存穿透和缓存雪崩。
缓存穿透:是指缓存命中率不高,缓存数据有问题,并没有起到很大的便利性。就像快递员每次收到大物件无法放进快递柜时,会在快递柜给你留了张纸条:请到XXX地领取你的快递。你肯定会说:这又不是寻宝游戏,直接通知我去XXX地不就行了!
缓存雪崩:就是你缓存数据的地方突然奔溃了,这下子本来在缓存处就要返回的请求,必须请求到后端并等待响应了。就像丰巣快递柜自动取件失灵了,每次都要快递员来送取快递了,快递员可能会忙不过来。
至于怎么解决,我们先按下不表,以后会跟大家说清楚,这里主要记得有这么二个概念就行。
小结
本章是对缓存概念的一个整体介绍,让你对缓存有个全方面的了解,你需要掌握的知识点如下:
1 缓存和缓冲的区别是什么?
2 理解计算机CPU多级缓存和缓冲类设计原理
3 从架构角度作为第一维度如何划分缓存类别,每层的缓存对象、缓存方式,常用技术工具有哪些?
4 衡量缓存的重要指标是什么?
5 不好的缓存设计可能会有什么问题?
后面我会对每一层缓存方式和缓存技术工具做详细的介绍,希望本节对你有所帮助。