博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Ehcache的简单学习1-Ehcache和Spring的结合使用
阅读量:6243 次
发布时间:2019-06-22

本文共 7490 字,大约阅读时间需要 24 分钟。

hot3.png

一、Ehcache的了解

JAVA缓存实现方案有很多,最基本的自己使用Map去构建缓存,或者使用memcached或Redis,但是上述两种缓存框架都要搭建服务器,而Map自行构建的缓存可能没有很高的使用效率,那么我们可以尝试一下使用Ehcache缓存框架。

Ehcache主要基于内存缓存,磁盘缓存为辅的,使用起来方便。下面介绍如何在项目中使用Ehcache

二、入门教程

1.maven引入

nexus.center
local private nexus
http://search.maven.org
true
false
net.sf.ehcache
ehcache
2.10.4

2.建立ehcache.xml

放在maven项目中的src/main/resources目录中。

Xml配置说明:

diskStore:当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口)  

<diskStore path="">:用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index  【注意:System.getProperty("java.io.tmpdir")可以查看位置!】

name:【必须】缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里)。

maxElementsInMemory:缓存最大个数。

eternal【必须】:对象是否永久有效,一但设置了,timeout将不起作用。 

timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 

timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。

overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。

diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。当数据从内存中转到磁盘时,会先将数据转入此缓存,然后由后台线程将数据从缓存中持久化到磁盘。如果遇到OutOfMemory错误时,可以尝试减小这个值。改进磁盘写入性能时,尝试增加这个值。将日志级别开到Trace,当DiskStore执行磁盘写入时,可以看到对应日志

maxElementsOnDisk:硬盘最大缓存个数【旧版】。

diskPersistent:是否缓存虚拟机重启期数据,默认为false,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件 这个文件中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存 要想把cache真正持久化到磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法。

diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。

memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 

clearOnFlush:内存数量最大时是否清除。当flush()方法调用时,MemoryStore是否清空其内容,默认为 true,即清空。

maxEntriesLocalHeap【必须】:堆内存中最大缓存对象数,0没有限制。与maxElementsInMemory(旧版本)类似!在实际使用中,在非分布式部署条件下,无限等效于Integer.MAX_SIZE (2147483647)。在分布式部署条件下,缓存项数量由Terracotta Server Array资源上限决定。

maxEntriesLocalDisk【必须】:磁盘中的最大对象数,默认为0不限制

===========================================

overflowToOffHeap:此属性仅在使用Ehcache企业版时有效。设置为true,缓存将使用非堆内存,非堆内存并非由Java管理,与Java垃圾回收无关。默认为false。

maxBytesLocalHeap:定义保存在Java虚拟机堆内存中的缓存项的最大字节数。 定义时格式如下<number>k|K|m|M|g|G,其中k|K代表千字节,m|M代表兆字节,g|G代表吉字节。    

 举例:maxBytesLocalHeap="2g"将使用2G堆内存。此属性与maxEntriesLocalHeap互斥,指定了此属性,则不能指定maxEntriesLocalHeap。如果设定过CacheManager的maxBytesLocalHeap属性,也不能使用此属性。放入缓存的缓存项将使用net.sf.ehcache.pool.sizeof.SizeOf方法计算其字节数。如果希望在计算字节数时忽略对象树种的某些属性,请参考net.sf.ehcache.pool.sizeof.annotations.IgnoreSizeOf注解。

maxBytesLocalOffHeap:此属性仅在使用Ehcache企业版时有效。设置本缓存区使用的非堆内存的大小。指定此属性,将默认设置overflowToOffHeap 为true。如果特别指定了overflowToOffHeap=”false”,将禁止使用非堆内存注意:当使用非堆内存时,推荐将maxEntriesLocalHeap设置为大于等于100,否则将严重影响性能。也将看到一条警告日志。非堆内存最小值为128MB,没有上限。

maxBytesLocalDisk:和maxBytesLocalHeap属性类似,不过指定的是存储在本地磁盘上的缓存项最大可使用的字节数

statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计。

copyOnRead:当缓存项被读出时,是否返回一份它的拷贝(返回对象是缓存中 对象的拷贝)。默认false。

copyOnWrite:当缓存项被写入时,是否写入一份它的拷贝(写入缓存的是写入 对象的拷贝)。默认false。

3.与Spring的CacheManager结合

classpath*:*.properties

注意:我们要绑定cache:annotation-driven的前缀cache .可以不用版本号!为啥不用写版本号,可以参考我的博客:

xmlns:cache="http://www.springframework.org/schema/cache"

http://www.springframework.org/schema/cache 

                        http://www.springframework.org/schema/cache/spring-cache.xsd"

4.代码使用

package com.book.web.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.Cache;import org.springframework.cache.Cache.ValueWrapper;import org.springframework.cache.CacheManager;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.book.core.model.User;/** * ehcache测试类 * @author liweihan * */@Controller@RequestMapping("/cache")public class TestEhCacheController {		@Autowired	private CacheManager cacheManager;		private static Logger logger = LoggerFactory.getLogger(TestEhCacheController.class);		/**	 * 测试:放入缓存和取数据	 * @return	 */	@ResponseBody	@RequestMapping("/testa")	public String testA() {		//获取testa缓存容器		Cache cache = cacheManager.getCache("cachea");		User user = new User();		user.setId(1);		user.setName("hanchao");				//将数据放入缓存		cache.put(1,user);				//获取数据		//方法1		User user2 = (User) cache.get(1).get();		logger.info("result1:" +  user2.getName());				//方法2		User user3 = cache.get(1, User.class);		logger.info("result2:" + user3.getName());				return "a";	}	/**	 * 测试取数据	 * @return	 */	@ResponseBody	@RequestMapping("/testb")	public String testB() {		//获取testa缓存容器		Cache cache = cacheManager.getCache("cachea");				//获取数据		//方法1//		User user2 = (User) cache.get(1).get();//		logger.info("result1:" + user2.getName());				//方法2		/*User user3 = cache.get(1, User.class);		logger.info("result2:" +  user3.getName());*/				//☆☆注意事项:key的类型必须也一样!☆☆/*		User user = (User) cache.get("1").get();		logger.info("类型不一样不行:" + user.getName());*/				//方法3:避免获取失效缓存时出现异常的情况		ValueWrapper valueWrapper = cache.get(1);		if (valueWrapper != null) {			User user = (User)valueWrapper.get();			logger.info("result3:" +  user.getName());		}				return "b";	}		/**	 * 测试删除数据	 * @return	 */	@ResponseBody	@RequestMapping("/testc")	public String testC() {		//获取缓存容器		Cache cache = cacheManager.getCache("cachea");		cache.evict(1);		return "c";	}}

我用的是springmvc,所以,写法是上面的。可以通过:

http://localhost:8080/cache/testa ,

http://localhost:8080/cache/testb,

http://localhost:8080/cache/testc

进行测试,看打印的情况。

注意事项:put进去时的key是Long类型的,get的时候也只能传入对应Long类型的key才能获取到对应的value,如果传入的是String类型的key,即使两个key的值是一致的,也会导致无法获取到对应的value。

5.LRU和LFU的区别

LRU和LFU是不同的!

LRU是最近最少使用页面置换算法(Least Recently Used),也就是首先淘汰最长时间未被使用的页面!

LFU是最近最不常用页面置换算法(Least Frequently Used),也就是淘汰一定时期内被访问次数最少的页!

比如,第二种方法的时期T为10分钟,如果每分钟进行一次调页,主存块为3,若所需页面走向为2 1 2 1 2 3 4

注意,当调页面4时会发生缺页中断

若按LRU算法,应换页面1(1页面最久未被使用) 但按LFU算法应换页面3(十分钟内,页面3只使用了一次)

可见LRU关键是看页面最后一次被使用到发生调度的时间长短,

而LFU关键是看一定时间段内页面被使用的频率!

三、参考链接

不与spring结合的ehcache链接

 

Java缓存Ehcache-核心类和方法介绍及代码实例

详解:

原理:

 

关于Java缓存,可以参考一下这篇文章:

Ehcache官网地址:

四、Ehcache的集群

1.基本介绍

从Ehcache1.2版本开始,Ehcache就可以使用分布式的缓存了,从 1.7版本开始,开始支持共五种集群方案,分别是

Terracotta

RMI
JMS
JGroups
EhCache Server

其中有三种上最为常用集群方式,分别是 RMI、JGroups 以及 EhCache Server 。

其实我们在使用Ehcache分布式缓存的过程中,主要是以缓存插件的方式使用,如果我们想根据自己的需要使用分布式缓存那就需要自己开发来定制化,我们会发现其实Ehcache提供的分布式缓存并不是非常好用,有不少问题存在(具体问题可以参考想链接),所以对缓存数据一致性比较高的情况下,使用集中式缓存更合适,比如Redis、Memcached等。

2.Ehcache的注意点

《1.》比较少的更新数据表的情况。

《2.》对并发要求不是很严格的情况,多台应用服务器中的缓存是不能进行实时同步的。

《3.》对一致性要求不高的情况下,因为Ehcache本地缓存的特性,目前无法很好的解决不同服务器间缓存同步的问题,所以我们在一致性要求非常高的场合下,尽量使用Redis、Memcached等集中式缓存。

 EhCache一般要使用在比较少执行write操作的表(包括update,insert,delete等),一般很少修改的数据,放在Ehcache中比较适合。

3.使用Ehcache的瓶颈

《1.》缓存漂移(Cache Drift):每个应用节点只管理自己的缓存,在更新某个节点的时候,不会影响到其他的节点,这样数据之间可能就不同步了。

《2.》数据库瓶颈(Database Bottlenecks ):对于单实例的应用来说,缓存可以保护数据库的读风暴;但是,在集群的环境下,每一个应用节点都要定期保持数据最新,节点越多,要维持这样的情况对数据库的开销也越大。

4.参考链接

下面是个好文章:

转载于:https://my.oschina.net/hanchao/blog/1596172

你可能感兴趣的文章
一个初学者是如何制作移动端B站画友社区的
查看>>
互联网分布式微服务云平台规划分析--平台整体规划
查看>>
Swift对象转为C指针
查看>>
Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)
查看>>
ThinkSNS系统升级,版本多样化
查看>>
ecshop使用smtp发送邮件
查看>>
RubyInstaller
查看>>
21. SQL -- TSQL架构,系统数据库,文件,SQL 认证,TSQL语句
查看>>
CentOS6.0添加163和epel源
查看>>
使用组策略与脚本发布Office 2010
查看>>
Open××× 分配固定IP
查看>>
elk+redis centos6.6安装与配置
查看>>
linux下svn命令大全
查看>>
windows server 2008 在vm上安装
查看>>
我的友情链接
查看>>
谷果等手机刷机build.prop解析
查看>>
Vbox虚拟机下 Linux网络配置
查看>>
Vmware vsphere知识中易混淆和忽略的多个概念
查看>>
Android客户端和服务端如何使用Token和Session
查看>>
Python Pycharm导入第三方包
查看>>