超轻量级缓存技术——EhCache

1.技术背景:

系统缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能。缓存设想内存是有限的,缓存的时效性也是有限的,所以可以设定内存数量的大小可以执行失效算法,可以在内存满了的情况下,按照最少访问等算法将缓存直接移除或切换到硬盘上。

Ehcache从Hibernate发展而来,逐渐涵盖了Cache界的全部功能,是目前发展势头最好的一个项目,具有快速、简单、低消耗、扩展性强、支持对象或序列化缓存,支持缓存或元素的失效,提供LRU、LFU和FIFO缓存策略,支持内存缓存和硬盘缓存和分布式缓存机制等特点。其中Cache的存储方式为内存或磁盘(ps:无须担心容量问题)

2.EhCahe的类层次介绍:

主要分为三层,最上层是CacheManager,它是操作Ehcache的入口。可以通过CacheManager.getInstance()获得一个单子的CacheManager,或者通过CacheManager的构造函数创建一个新的CacheManager。每个CacheManger都管理多个Cache。每个Cache都以一种类Hash的方式,关联多个Element。Element就是我们用于存放缓存内容的地方。

3.环境搭建:

很简单只需要将ehcache-2.1.0-distribution.tar.gz和ehcache-web-2.0.2-distribution.tar.gz挤压的jar包放入WEB-INF/lib下。

再创建一个重要的配置文件ehcache.xml,可以从ehcache组件包中拷贝一个,也可以自己建立一个,需要放到classpath下,一般放于/WEB-INF/classed/ehcache.xml;具体的配置文件可以网上搜一下

4.实际运用

一个网站的首页估计是被访问次数最多的,我们可以考虑给首页做一个页面缓存;

缓存策略:应该是某个固定时间之内不变的,比如说2分钟更新一次,以应用结构page-filter-action-service-dao-db为例。

位置:页面缓存做到尽量靠近客户的地方,就是在page和filter之间,这样的优点就是第一个用户请求后,页面被缓存,第二个用户在请求,走到filter这个请求就结束了,需要在走到action-service-dao-db,好处当然是服务器压力大大降低和客户端页面响应速度加快。

首页页面缓存存活时间定为2分钟,也就是参数timeToLiveSeconds(缓存的存活时间)应该设置为120,同时timeToIdleSeconds(多长时间不访问缓存,就清楚该缓存)最好也设为2分钟或者小于2分钟。

接着我们来看一下SimplePageCachingFilter 的配置,

  1. <filter>
  2. <filter-name>indexCacheFilterfilter-name>
  3. <filter-class>
  4. net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
  5. <filter-class>
  6. <filter>
  7. <filter-mapping>
  8. <filter-name>indexCacheFilterfilter-name>
  9. <url-pattern>*index.actionurl-pattern>
  10. <filter-mapping>

将上述代码加入到web.xml,那么当打开首页时,你会发现2分钟才会有一堆sql语句出现在控制台,也可以调整为5分钟,总之一切尽在掌控之中。

当然,如果你像缓存首页的部分内容时,你需要使用SimplePageFragmentCachingFilter这个filter,我看一下:

  1. <filter>
  2. <filter-name>indexCacheFilterfilter-name>
  3. <filter-class>
  4. net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter
  5. <filter-class>
  6. filter>
  7. <filter-mapping>
  8. <filter-name>indexCacheFilterfilter-name>
  9. <url-pattern>*/index_right.jsp<url-pattern>
  10. <filter-mapping>

如此我们将jsp页面通过jsp:include到其他页面,这样就做到了页面局部缓存的效果,这一点貌似没有oscache的tag好用。

此外cachefilter中还有一个特性,就是gzip,也就是缓存中的元素是被压缩过的,如果客户端浏览器支持压缩的话,filter会直接返回压缩过的流,这样节省了带宽,把解压的工作交给了客户端浏览即可,当然如果客户端不支持gzip,那么filter会把缓存的元素拿出来解压后在返回给客户端浏览器(大多数爬虫是不支持gzip的,所以filter也会解压后在返回流)。

总之,Ehcache是一个非常轻量级的缓存实现,而且从1.2之后支持了集群,而且是hibernate默认的缓存provider,本文主要介绍Ehcahe对页面缓存的支持,但是它的功能远不止如此,要用好缓存,对J2ee中缓存的原理、适用范围、适用场景等等都需要比较深刻的理解,这样才能用好用对缓存。

为了大家通过实际例子加深了解与场景运用,在奉献一个实例:

*在Spring中运用EhCache

适用任意一个现有开源Cache Framework,要求可以Cache系统中service或者DAO层的get/find等方法返回结果,如果数据更新(适用了Create/update/delete),则刷新cache中相应的内容。

根据需求,计划适用Spring AOP+enCache来实现这个功能,采用ehCache原因之一就是Spring提供了enCache的支持,至于为何仅仅支持ehcache而不支持oscache和jbosscache就无从得知了。

AOP少不了拦截器,先创建一个实现了MethodInterceptor接口的拦截器,用来拦截Service/DAO的方法调用,拦截到方法后,搜索该方法的结果在cache中是否存在,如果存在,返回cache中结果,如果不存在返回数据库查询结果,并将结果返回到缓存。

  1. public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean
  2. {
  3. private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);
  4. private Cache cache;
  5. public void setCache(Cache cache) {
  6. this.cache = cache;
  7. }
  8. public MethodCacheInterceptor() {
  9. super();
  10. }
  11. /**
  12. * 拦截Service/DAO 的方法,并查找该结果是否存在,如果存在就返回cache 中的值,
  13. * 否则,返回数据库查询结果,并将查询结果放入cache
  14. */
  15. public Object invoke(MethodInvocation invocation) throws Throwable {
  16. String targetName = invocation.getThis().getClass().getName();
  17. String methodName = invocation.getMethod().getName();
  18. Object[] arguments = invocation.getArguments();
  19. Object result;
  20. logger.debug("Find object from cache is " + cache.getName());
  21. String cacheKey = getCacheKey(targetName, methodName, arguments);
  22. Element element = cache.get(cacheKey);
  23. Page 13 of 26
  24. if (element == null) {
  25. logger.debug("Hold up method , Get method result and create cache........!");
  26. result = invocation.proceed();
  27. element = new Element(cacheKey, (Serializable) result);
  28. cache.put(element);
  29. }
  30. return element.getValue();
  31. }
  32. /**
  33. * 获得cache key 的方法,cache key 是Cache 中一个Element 的唯一标识
  34. * cache key 包括包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser
  35. */
  36. private String getCacheKey(String targetName, String methodName, Object[] arguments) {
  37. StringBuffer sb = new StringBuffer();
  38. sb.append(targetName).append(".").append(methodName);
  39. if ((arguments != null) && (arguments.length != 0)) {
  40. for (int i = 0; i < arguments.length; i++) {
  41. sb.append(".").append(arguments[i]);
  42. }
  43. }
  44. return sb.toString();
  45. }
  46. /**
  47. * implement InitializingBean,检查cache 是否为空
  48. */
  49. public void afterPropertiesSet() throws Exception {
  50. Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");
  51. }
  52. }

上面的代码可以看到,在方法invoke中,完成了搜索cache/新建cache的功能

随后,再建立一个拦截器MethodCacheAfterAdvice,作用是在用户进行create/update/delete操作时来刷新、remove相关cache内容,这个拦截器需要实现AfterRetruningAdvice接口,将会在所拦截的方法执行后执行在afterReturning(object arg0,Method arg1,Object[] arg2,object arg3)方法中所预定的操作

  1. public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean
  2. {
  3. private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);
  4. private Cache cache;
  5. Page 15 of 26
  6. public void setCache(Cache cache) {
  7. this.cache = cache;
  8. }
  9. public MethodCacheAfterAdvice() {
  10. super();
  11. }
  12. public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws
  13. Throwable {
  14. String className = arg3.getClass().getName();
  15. List list = cache.getKeys();
  16. for(int i = 0;i<list.size();i++){
  17. String cacheKey = String.valueOf(list.get(i));
  18. if(cacheKey.startsWith(className)){
  19. cache.remove(cacheKey);
  20. logger.debug("remove cache " + cacheKey);
  21. }
  22. }
  23. }
  24. public void afterPropertiesSet() throws Exception {
  25. Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");
  26. }
  27. }

该方法获取目标class的全名,如:com.co.cache.test.TestServiceImpl,然后循环cache的key list,刷新/remove cache中所有和该class相关的element。

接着就是配置encache的属性,如最大缓存数量、cache刷新的时间等等。

  1. <ehcache>
  2. <diskStore path="c:\\myapp\\cache"/>
  3. <defaultCache
  4. maxElementsInMemory="1000"
  5. eternal="false"
  6. timeToIdleSeconds="120"
  7. timeToLiveSeconds="120"
  8. overflowToDisk="true"
  9. />
  10. <cache name="DEFAULT_CACHE"
  11. maxElementsInMemory="10000"
  12. eternal="false"
  13. timeToIdleSeconds="300000"
  14. timeToLiveSeconds="600000"
  15. overflowToDisk="true"
  16. />
  17. </ehcache>

这里需要注意的是defaultCache定义了一个默认的cache,这个Cache不能删除,否则会抛出No default cache is configured异常。另外由于使用拦截器来刷新Cache内容,因此在定义cache生命周期时可以定义较大的数值,timeToIdleSeconds="30000000",timeToLiveSeconds="6000000",好像还不够大?

然后再将Cache和两个拦截器配置到Spring的配置文件cache.xml中即可,需要创建两个“切入点”,分别用于拦截不同方法名的方法。在配置application.xml并且导入cache.xml。这样一个简单的Spring+Encache框架就搭建完成。

由于时间关系就介绍到这里,以后有机会还会介绍Ehcache在分布式集群系统中的使用,谢谢大家。

原文地址:https://www.cnblogs.com/firstdream/archive/2012/03/19/2406201.html

作者:有梦就能实现

原文地址:https://www.cnblogs.com/likearock/p/9645922.html

时间: 2024-10-10 09:50:49

超轻量级缓存技术——EhCache的相关文章

Hibernate的缓存技术EhCache的配置

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

ehcache缓存技术的特性

Ehcache是现在最流行的纯Java开源缓存框架,配置简单.结构清晰.功能强大,最初知道它,是从hibernate的缓存开始的.网上中文的EhCache材料以简单介绍和配置方法居多,如果你有这方面的问题,请自行google:对于API,官网上介绍已经非常清楚,请参见官网:但是很少见到特性说明和对实现原理的分析,因此在这篇文章里面,我会详细介绍和分析EhCache的特性,加上一些自己的理解和思考,希望对缓存感兴趣的朋友有所收获. 一.特性一览,来自官网,简单翻译一下: 1.快速轻量 过去几年,诸

EHCache页面缓存技术

EHCache的jar包 :http://ehcache.org/downloads/catalog   这里用的是EHcache的web包. 在项目的web.xml文件中加入一个filter: <!--EHCache 页面缓存技术,该页面缓存技术用于page -> filter之间,若是局部页面缓存,           则用SimplePageFragmentCachingFilter,但应注意局部页面要被其他页面 jsp:include     -->     <filter

十亿级视频播放技术优化揭密

本文为转载文章,文章来自:王辉|十亿级视频播放技术优化揭密 QCon是由InfoQ主办的全球顶级技术盛会,每年在伦敦.北京.东京.纽约.圣保罗.上海.旧金山召开.自 2007年 3月份首次举办以来,已经有超万名高级技术人员参加过QCon大会.QCon内容源于实践并面向社区,演讲嘉宾依据热点话题,面向 5年以上工作经验的技术团队负责人.架构师.工程总监.高级开发人员分享技术创新和最佳实践. 4月18日性能优化面面观专题会议上,腾讯研发总监王辉以“十亿级视频播放技术优化揭秘”为主题,用QQ空间的日均

(转)java缓存技术,记录

http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/articles/cache-static-files-with-jnotify-and-ehcache 介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI

PHP 缓存技术

PHP缓存包括PHP编译缓存和PHP数据缓存两种. PHP是一种解释型语言,属于边编译边运行的那种.这种运行模式的优点是程序修改很方便,但是运行效率却很低下. PHP编译缓存针对这种情况做改进处理,使得PHP语言只要运行一次,就可以把程序的编译结果缓存起来. PHP编译缓存: 目前最常见的PHP编译缓存工具有:APC,Accelerator,xcache(国产)等. PHP是一种解释型语言,在PHP语言执行代码的时候,需要下面两步: 1.编译过程.PHP读取文件,并编译该文件,然后生成能够在Ze

Hibernate-二级缓存

与Session相对的是,SessionFactory也提供了相应的缓存机制.SessionFactory缓存可以依据功能和目的的不同而划分为内置缓存和外置缓存. SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本,而预定义SQL语句是在 Hibernate初始化阶段根据映射元数据推导出来的.SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义 SQL语句,因此SessionFactory不需要进行内

强大的Spring缓存技术(上)

缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配置方法,展现了 spring cache 的强大之处,然后介绍了其基本的原理,扩展点和使用场景的限制.通过阅读本文,你应该可以短时间内掌握 spring 带来的强大缓存技术,在很少的配置下即可给既有代码提供缓存能力. 概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)

Java的进程内缓存框架:EhCache (转)

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