上一章我们讨论了Cookie的概念和js使用方法。这一章我们来讨论Cache:一个同样在开发过程中经常听到的名词——缓存。
Cache是什么?
缓存就是用来避免频繁的到主存储器(一般来说可能是数据库,结构化的磁盘文件,远程网络接口,程序接口等等提供数据返回的)获取数据而建立的一个存取更快的临时存储器(缓存)。一般来说,缓存比主存储器更小(不一定,也可能是存储的数据结构不一样,但是存取速度非常快),存储的容量也比较小,但是存取速度非常快。
简而言之,缓存一般有下面3个作用:
存储频繁访问的数据
临时存储耗时的计算结果
内存缓存减少磁盘IO
Cache的类型
我们会听到各种人说到缓存,但是大家讨论的缓存是有很大区别的。为什么呢?因为在整个系统开发的各个部分,缓存都担任着重要的角色。不同开发所说的缓存,是不同类型的缓存。缓存大致可以分为下面几种:
数据库端缓存
数据库端缓存可以用“空间换时间”来比喻。比如建一个表来存储另外一个表某个类型的数据的总条数,在每次更新数据的时候更新 数据表和统计条数的表。在需要获取某个类型的数据的条数的时候,就不需要select count去查询,直接查询统计表就可以了,这样可以提高查询的速度和数据库的性能。
应用层缓存
我们也经常从和前端接口的业务研发人员(RD)口中听到缓存这个词。应用层缓存也可以叫做服务器端缓存。有以下几种:
缓存数据库的查询结果,减少数据的压力。这个在大型网站是必须做的。
缓存磁盘文件的数据。比如常用的数据可以放到内存,不用每次都去读取磁盘,特别是密集计算的程序,比如中文分词的词库。
缓存某个耗时的计算操作,比如数据统计。
前端缓存
我们这里说的前端缓存可以理解为一般使用的cdn技术,利用squid等做前端缓冲技术,主要还是针对静态文件类型,比如图片,css,js,html等静态文件。一般像天猫等用户量大的系统需要使用这个前端缓存。其实简而言之,就是为了让用户能快速的访问页面,将前端静态文件用缓存的方式分布全球各地,用户访问时可以就近下载,加快访问速度。
浏览器缓存
浏览器端的缓存,可以让用户请求一次之后,下一次不在从服务器端请求数据,直接从本地缓存读取,可以减轻服务器负担也可以加快用户的访问速度。调试页面时强刷更新缓存指的就是客户端缓存,这里我们着重讨论浏览器端缓存。
浏览器缓存机制
浏览器缓存分为两个部分:
页面html的缓存:HTTP协议定义的缓存机制(如: Expires; Cache-control等)。
图片,css,js,flash等缓存:通过服务器配置实现将相应资源缓存在浏览器端。
主要讨论页面html缓存。
页面html缓存
页面缓存状态是由http header决定的,一个浏览器请求信息,一个是服务器响应信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP/1.0规定,Cache-Control由HTTP/1.1规定。
从图中我们可以看到原理主要分三步:浏览器第一次请求,通过http的header报头,附带Expires,Cache-Control,Last-Modified/Etag向服务器请求,此时服务器记录第一次请求的Last-Modified/Etag;当浏览器再次请求的时候,附带Expires,Cache-Control,If-Modified-Since/Etag向服务器请求;服务器根据第一次记录的Last-Modified/Etag和再次请求的If-Modified-Since/Etag做对比,判断是否需要更新,然后响应请求。
这几个参数有什么作用呢?下面我们对这些参数进行说明:
Cache-Control:值为Public,响应会被缓存,并且在多用户间共享;Private,响应只能够作为私有的缓存,不能再用户间共享;no-cache,不进行缓存;max-age=x,缓存时间,以秒为单位;must-revalidate,如果页面是过期的,则去服务器进行获取。
Expires:设置显示页面的过期时间。
Last-Modified:请求对象最后一次的修改时间,用来判断缓存是否过期,通常由服务器上文件的时间信息产生。
If-Modified-Since:客户端发送请求附带的信息,指浏览器缓存请求对象的最后修改日期,用来和服务器端的Last-Modified做比较。
Etag:ETag是一个可以与Web资源关联的记号(token),和Last-Modified功能才不多,也是一个标识符,一般和Last-Modified一起使用,加强服务器判断的准确度。