缓存概览

一、缓存简介

1.什么是缓存

维基百科上的定义: 凡是位于速度相差较大的两种硬件之间的,用于协调两者数据传输速度差异的结构,均可称之为Cache

生成高性能、可缩放的 Web 应用程序最重要的因素之一是能够在首次请求项时将这些项存储在内存中,不管它们是数据对象、页还是页的某些部分。 可以将这些项缓存或存储在 Web 服务器上或请求流中的其他软件上,如代理服务器或浏览器。 使您能够避免重新创建满足先前请求的信息,尤其是那些需要大量处理器时间或资源的信息。

2.缓存分类

       从本质上来讲,缓存分为输出缓存和应用程序数据缓存。输出缓存是将生成的页面、图片、JS文件等保存在本地或内存,当请求的时候将本地或内存中的输出返回。实现原理一般是通过http响应头中的Cache设置,可以在程序中实现对http响应头的修改。应用程序缓存是将数据存放在内存的Cache容器中,读取时先从内存中读取,从而提高数据访问的效率。

缓存

分类

用途

应用程序数据缓存

数据缓存

减少对数据库的请求

Web服务器缓存

输出缓存

减少应用服务器的请求

客户端浏览器缓存

输出缓存

减少对网站的请求

 

2.1输出缓存(客户端浏览器的缓存)

一般而言,在Web服务器中可以进行输出缓存的设置,并且默认会对静态的js、图片等设置响应缓存。设置后,web服务器在返回的http响应头中设置缓存失效时间,例如“Expires Fri Nov 12 2010 12:04:48 GMT+0800”。这样,在发出请求的浏览器、响应请求的 Web 服务器以及请求或响应流中任何其他具有缓存功能的设备(如代理服务器)上都可以缓存页。

浏览器接收到http响应后,根据响应头中的缓存设置进行缓存缓存后,同一台机器发出的请求在缓存失效前就会直接使用本地的缓存,不会再向服务器进行请求。

比如,使用firebug可以查看到http应答头中的缓存失效时间。

<!--[endif]-->

 

2.2输出缓存(位于Web服务器之前的缓存服务层)

       这个层面的缓存旨在通过Web服务器前的缓存服务器,通常是反向代理服务器,比如Squid,或其他Web加速设备,比如F5

       工作原理:用户在访问Web应用时先经过缓存服务器,一般都是反向代理服务器或其他流量分发设备,在此服务器上缓存图片、JS文件、Html等,如果有缓存,则直接返回给用户结果,无需将请求再发给Web服务器,从而有效的减轻了Web服务器的负载。也叫Web加速技术。   

 

<!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" alt="1123213" style='width:300pt;height:129.75pt'> <v:imagedata src="file:///C:\DOCUME~1\zoe\LOCALS~1\Temp\msohtmlclip1\01\clip_image003.gif" o:href="http://www.chentaoqian.com/wp-content/uploads/2009/07/1123213.gif" /> </v:shape><![endif]--><!--[if !vml]-->1123213<!--[endif]-->

代理服务器缓存后,客户端发过来的相同的请求就会直接使用在代理服务器上的缓存,而不会再向Web服务器请求。

当前一些设备,比如F5Web加速技术,也可以对部分动态的页面进行缓存。

       此部分不是本文档讨论的重点,详细用SquidWeb加速可参考相关资料如

http://www.opent.cn/a/106/2564.shtml

http://www.chentaoqian.com/archives/408

2.3输出缓存(动态语言的Web容器层)

使用输出缓存,你可以缓存最后输出的HTML页面,当相同的页面再次请求的时候,缓存功能允许利用缓存满足对页的后续请求,这样就不需要再次运行最初创建该页的代码。 对站点中访问最频繁的页进行缓存可以充分地提高 Web 服务器的吞吐量(通常以每秒的请求数计算)。

<!--[if !supportLists]-->l   <!--[endif]-->缓存页面

       用户请求某一缓存页时,Web服务器根据已经为该页定义的缓存策略确定其缓存输出是否仍有效。 如果该输出有效,则将该缓存输出发送到客户端,并且不重新处理该页。

       对于此种方式,ASP.netJava都有对应的实现,相比之下,ASP.net可以直接在aspx页面上配置实现,也可以在程序中控制,相当简单。Java解决方案中,很多缓存框架提供同样的服务,OSCache也提供标签的方式设置页面输出缓存,但OSCache项目从2007年后没有更新,不建议使用。EHCache也可以实现页面输出缓存,但过程没有OSCache简洁。

       多数缓存方案也支持缓存同一页中的多个版本,比如,根据初始请求 (HTTP GET) 中的查询字符串,回发时传递的控制值(HTTP POST 值),随请求传递的 HTTP 标头,发出请求的浏览器的主版本号等因素存储不同的缓存版本,根据不同的请求返回不同的缓存版本。

      

<!--[if !supportLists]-->l   <!--[endif]-->缓存部分页面

       有时缓存整个页是不现实的,因为页的某些部分可能在每次请求时都需要更改。 在这些情况下,只能缓存页的一部分。比如,对某些控件进行缓存。

2.4应用程序数据缓存(应用程序数据访问层)

应用程序缓存是将数据存放在内存的Cache容器中,读取时先从内存中读取,从而提高数据访问的效率。

!vml]-->ASP.NET缓存机制简析(图二)

关于数据的更新与缓存的失效

有的缓存框架与数据库绑定提供了通知机制,比如说ASP.net的缓存框架和Sql Server绑定,当Sql Server数据库变动时,会自动通知缓存更新数据。但这种解决方案目前还只能和Sql Server绑定,并且似乎会在数据表上自动增加trigger

比较常见的数据更新方式是在程序中控制,比如在数据变更时通知对应缓存清除数据,可以在更新数据时就写入新数据到缓存或者只是清除,等用户读取数据时再写入缓存。推荐采用后一种方式。

比较好的处理方式推荐用AOP,对数据变更的方法织入清除缓存的代码,将缓存清除。这样可以将清除缓存和代码的业务逻辑切割开来。

3.集群与分布式缓存

对于数据的缓存在应用服务器集群时会遇到脏数据的问题。因为数据的改变的通知只能通知到本地的缓存,在其他机器上的缓存则继续使用着本地缓存中错误的数据。

解决这一问题的方法可以使用独立的缓存服务器,比如MemCache,当多台集群都使用同一缓存服务器,则不存在更新数据的问题。这也用来解决不同进程间需要使用共同的缓存数据的问题。

进一步,我们涉及到缓存服务器集群的问题。当缓存数据量大到单机资源无法承受的时候,需要进行缓存服务器集群。传统缓存服务器集群采用数据复制的技术,当集群变大的时候效率相当成问题。MemCache的高明之处在于,MemCache集群的节点之间没有任何通信,它在客户端连接中实现一个算法,将存储对象在各节点中做一个分配。从而实现了memcache的集群。

<!--[endif]-->

二、ASP.NET缓存介绍

可参考msdn文档:ASP.NET 缓存

http://msdn.microsoft.com/zh-cn/library/xsbfdd8c.aspx

以及

PetshopAsp.net缓存

http://www.shehui001.com/htm/2009810/198.htm

 

三、EHCache介绍

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider

下图是 Ehcache 在应用程序中的位置:

主要的特性有:

1. 快速.
2.
简单.
3.
多种缓存策略
4.
缓存数据有两级:内存和磁盘,因此无需担心容量问题
5.
缓存数据会在虚拟机重启的过程中写入磁盘
6.
可以通过RMI、可插入API等方式进行分布式缓存
7.
具有缓存和缓存管理器的侦听接口
8.
支持多缓存管理器实例,以及一个实例的多个缓存区域
9.
提供Hibernate的缓存实现
10.
等等

详细可参考EHCache官方网站提供的EHCacheUserGuide http://ehcache.org

四、OSCache介绍

OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。

支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。

       但遗憾的是,OSCache官方网站上的项目自从2007年开始停止了更新,从后继发展的角度来说,Java的本地缓存框架应选择EHCache

五、MemCache介绍

memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。现在已成为 豆瓣、Facebook Vox 等众多服务中提高Web应用扩展性的重要因素。

memcached作为高速运行的分布式缓存服务器,具有以下的特点。

 

•协议简单

•基于libevent的事件处理

•内置内存存储方式

memcached不互相通信的分布式

 

<!--[if !supportLists]-->l   <!--[endif]-->协议简单

memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet 也能在memcached上保存数据、取得数据。下面是例子:

 

$ telnet localhost 11211

Trying 127.0.0.1...

Connected to localhost.localdomain (127.0.0.1).

Escape character is '^]'.

set foo 0 0 3     (保存命令)

bar               (数据)

STORED            (结果)

get foo           (取得命令)

VALUE foo 0 3     (数据)

bar               (数据)协议文档位于memcached的源代码内,也可以参考以下的URL

 

http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt基于libevent的事件处理

libevent是个程序库,它将LinuxepollBSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。 memcached使用这个libevent库,因此能在LinuxBSDSolaris等操作系统上发挥其高性能。关于事件处理这里就不再详细介绍,可以参考Dan KegelThe C10K Problem

 

libevent: http://www.monkey.org/~provos/libevent/

The C10K Problem: http://www.kegel.com/c10k.html

<!--[if !supportLists]-->l   <!--[endif]-->内置内存存储方式

为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。 memcached本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。关于内存存储的详细信息,本连载的第二讲以后前坂会进行介绍,请届时参考。

 

<!--[if !supportLists]-->l   <!--[endif]-->memcached不互相通信的分布式

memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。它在客户端连接中实现一个算法,将存储对象在各节点中做一个分配。从而实现了memcache的集群。

详细介绍可参考 memcached完全剖析系列教程

http://www.plhwin.com/memcached-tutorial-base-1/

 

猜你喜欢

转载自sailorls.iteye.com/blog/942206