看着文档学ehcache
来源:互联网 发布:非洲人眼中的中国知乎 编辑:程序博客网 时间:2024/05/17 01:15
简介:纯java实现的缓存组件(jar包),最主要的作用还是做应用内缓存(进程内),比如hibernate就默认使用ehcache做缓存。我们可以创建多个缓存(cache),缓存中以key-value的形式存储数据,数据结构较为单一。
存储位置:
heap:由GC管理的JVM堆
offheap:堆外内存(非JVM的堆)
disk:持久化到硬盘,cache.destroy()方法可以删除硬盘上的缓存
其他功能
Eviction Advisors
缓存策略,说白了就是控制哪些缓存数据可存储,哪些不可存储,比如可以只让key为偶数的存储,或者只有value为String类可以存储。我们可以定义一个实现了EvictionAdvisor接口的类来控制。
User Managed Caches
由用户自己管理的缓存,不由CacheManager管理,用户可以自己控制cache的生命周期等等。但是为了方便,一般都是由CacheManager来管理。
Transactions Support
支持事务,我觉得一般用不到,如果它仅仅是一个缓存,并且缓存的逻辑会包含在service方法里,而service方法由spring的事务来管理,那么没必要用到它。
Cache-through
包括read-through和write-through,把缓存作为SOR(system of record),我个人还没弄清楚作为系统级别的缓存数据有什么作用
ehcache与redis的区别
1.redis的数据结构比较丰富,有key-value、hash、set等;ehcache比较简单,只有key-value
2.ehcache直接在jvm虚拟机中缓存,速度快,效率高;但是缓存共享麻烦,集群分布式应用不方便。redis是通过socket访问到缓存服务,效率ecache低,比数据库要快很多,处理集群和分布式缓存方便,有成熟的方案。如果是单个应用或者对缓存访问要求很高的应用,用ehcache。如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。
编程方式配置cache
下面是两个例子
import org.ehcache.Cache;import org.ehcache.CacheManager;import org.ehcache.config.builders.CacheConfigurationBuilder;import org.ehcache.config.builders.CacheManagerBuilder;import org.ehcache.config.builders.ResourcePoolsBuilder;import org.junit.Test;/** * writer: holien * Time: 2017-08-11 11:52 * Intent: 入门测试ehcache */public class EhCacheTest { @Test public void testEhcache() { // 创建缓存管理器和一个叫“preConfigured”的缓存实例 CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .withCache("preConfigured", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) .build(); // 初始化缓存管理器 cacheManager.init(); Cache preConfigured = cacheManager.getCache("preConfigured", Long.class, String.class); preConfigured.put(1L, "zheng pens"); // 覆盖上一个值 preConfigured.put(1L, "pens"); System.out.println(preConfigured.get(1L)); System.out.println(preConfigured.containsKey(1L)); // 不存在的key-value返回null System.out.println(preConfigured.get(2L)); // 不允许值为null,报空指针错误// preConfigured.put(3L, null); // 不在创建cacheManeger时创建缓存实例,单独创建 Cache cache2 = cacheManager.createCache("cache2", CacheConfigurationBuilder.newCacheConfigurationBuilder( Integer.class, String.class, ResourcePoolsBuilder.heap(5))// .withEvictionAdvisor(new CustomEvictionAdvisor()) .build()); cache2.put(100, "hello"); System.out.println(cache2.get(100)); }}这个例子中把缓存的数据存储到硬盘
import org.ehcache.PersistentUserManagedCache;import org.ehcache.config.builders.ResourcePoolsBuilder;import org.ehcache.config.builders.UserManagedCacheBuilder;import org.ehcache.config.units.MemoryUnit;import org.ehcache.core.spi.service.LocalPersistenceService;import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration;import org.ehcache.impl.config.persistence.UserManagedPersistenceContext;import org.ehcache.impl.persistence.DefaultLocalPersistenceService;import org.junit.Test;import java.io.File;/** * writer: holien * Time: 2017-08-11 22:40 * Intent: 使用ehcache的持久化功能 */public class PersistenceCacheTest { @Test public void testPersistenceCache() throws Exception { LocalPersistenceService persistenceService = new DefaultLocalPersistenceService( new DefaultPersistenceConfiguration(new File("E:\\"))); PersistentUserManagedCache<Long, String> cache = UserManagedCacheBuilder.newUserManagedCacheBuilder(Long.class, String.class) .with(new UserManagedPersistenceContext<Long, String>("persistentCache", persistenceService)) .withResourcePools(ResourcePoolsBuilder.newResourcePoolsBuilder() .disk(10L, MemoryUnit.MB, true)) .build(true); // 把缓存只存进硬盘里,只要persistenceService相同,即使关闭,再次启动还是可以读取数据 cache.put(42L, "The Answer!"); System.out.println(cache.get(42L));// cache.remove(44L); // 手动关闭和销毁 cache.close(); // 删除硬盘上的缓存// cache.destroy(); // 停止服务 persistenceService.stop(); }}
创建CacheConfiguration时设置该缓存的entry的过期时间
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(20, TimeUnit.SECONDS)))官方实例的xml文件,各种属性作一个介绍
<ehcache:config xmlns:ehcache="http://www.ehcache.org/v3" xmlns:jcache="http://www.ehcache.org/v3/jsr107"> <!-- services to be managed and lifecycled by the CacheManager 用来管理缓存管理器的生命周期,当使用UserCacheManager才需要用到 --> <ehcache:service> <!-- One element in another namespace, using our JSR-107 extension as an example here 使用Jcache作为接口,即JSR-107扩展才需要用到 --> <jcache:defaults> <jcache:cache name="invoices" template="myDefaultTemplate"/> </jcache:defaults> </ehcache:service> <!-- 必须拥有的属性,为cache起一个别名,给cacheManager管理 --> <ehcache:cache alias="productCache"> <!-- key类型默认是Object类型 --> <ehcache:key-type copier="org.ehcache.impl.copy.SerializingCopier">java.lang.Long</ehcache:key-type> <!-- value类型默认是Object类型 --> <ehcache:value-type copier="org.ehcache.impl.copy.SerializingCopier">com.pany.domain.Product</ehcache:value-type> <ehcache:expiry> <!-- * <ttl>, time to live; 从创建entry到过期的时间 * <class>, for a custom Expiry implementation; 自定义过期类 * <none>, for no expiry 默认不过期 下面为entry的空闲时间 --> <ehcache:tti unit="minutes">2</ehcache:tti> </ehcache:expiry> <!-- 可选,advice,写一个实现了EvictionAdvisor接口的类来控制哪些entry被驱逐(比如key为偶数的才可以进行缓存) --> <ehcache:eviction-advisor>com.pany.ehcache.OddEvictionAdvisor</ehcache:eviction-advisor> <!-- 把cache当作系统缓存(系统记录)来使用 Let's you configure your cache as a "cache-through", i.e. a Cache that uses a CacheLoaderWriter to load on misses, and write on mutative operations. --> <ehcache:loader-writer> <!-- 下面是自定义的一个类,我还没弄明白为什么要把缓存升级为系统缓存,这里留个疑问... --> <ehcache:class>com.pany.ehcache.integration.ProductCacheLoaderWriter</ehcache:class> <!-- Any further elements in another namespace --> </ehcache:loader-writer> <!-- The maximal number of entries to be held in the Cache, prior to eviction starting 此缓存最多可存储的键值对数 --> <ehcache:heap unit="entries">200</ehcache:heap> </ehcache:cache> <!-- 缓存模板,可被其他缓存引用,避免重复定义相似的cache --> <ehcache:cache-template name="myDefaultTemplate"> <ehcache:expiry> <ehcache:none/> </ehcache:expiry> </ehcache:cache-template> <!-- 引用上面定义的模板 --> <ehcache:cache alias="customerCache" uses-template="myDefaultTemplate"> <!-- Adds the key and value type configuration 在模板的基础上添加key、value的类型 --> <ehcache:key-type>java.lang.Long</ehcache:key-type> <ehcache:value-type>com.pany.domain.Customer</ehcache:value-type> <!-- Overwrites the capacity limit set by the template to a new value 可以通过重写覆盖模板的属性 --> <ehcache:heap unit="entries">200</ehcache:heap> </ehcache:cache></ehcache:config>
使用我自己定义的ehcache.xml配置的cache
<ehcache:config xmlns:ehcache="http://www.ehcache.org/v3" xmlns:jcache="http://www.ehcache.org/v3/jsr107"> <ehcache:cache alias="test"> <ehcache:key-type>java.lang.Long</ehcache:key-type> <ehcache:value-type>java.lang.String</ehcache:value-type> <ehcache:expiry> <ehcache:ttl>1000</ehcache:ttl> </ehcache:expiry> <ehcache:heap unit="entries">2</ehcache:heap> </ehcache:cache></ehcache:config>
import org.ehcache.Cache;import org.ehcache.CacheManager;import org.ehcache.config.builders.CacheManagerBuilder;import org.ehcache.xml.XmlConfiguration;import org.junit.Test;import java.net.URL;/** * writer: holien * Time: 2017-08-13 14:24 * Intent: 使用xml配置cache */public class XmlConfugureTest { @Test public void testXmlConfiguration() throws Exception {// URL location = new URL("file:E:\\IdeaProjects\\ehCacheTest\\web\\ehcache.xml"); URL location = getClass().getResource("/ehcache.xml"); System.out.println(location.toString()); XmlConfiguration xmlConfiguration = new XmlConfiguration(location); CacheManager cacheManager = CacheManagerBuilder.newCacheManager(xmlConfiguration); cacheManager.init(); Cache cache = cacheManager.getCache("test", Long.class, String.class); cache.put(1L, "111"); cache.put(2L, "222"); System.out.println(cache.get(1L)); System.out.println(cache.get(2L)); }}
当然,最好还是由spring管理cacheManager,然后使用xml来配置cache的属性,这样管理起来比较方便,在另一篇文章,讲讲ehcache2与spring的整合以及注解。
cache运行期间添加监听器ListenerObject listener = new ListenerObject(); 这个ListenerObject类就是我们自己定义的继承了CacheEventAdapter抽象类的类。
cache.getRuntimeConfiguration().registerCacheEventListener(listener, EventOrdering.ORDERED, EventFiring.ASYNCHRONOUS, EnumSet.of(EventType.CREATED, EventType.REMOVED));
cache运行期间解除监听器
cache.getRuntimeConfiguration().deregisterCacheEventListener(listener);
官方3.1v文档说提供了CacheEventAdapter抽象类方便我们重写监听器的方法,但是CacheEventAdapter 里的方法却是protected的,只能通过下载源码,然后改写源码重新打jar包,比较麻烦,后期修改也麻烦,也许是一个bug。
总结
ehcache也有集群的功能,但是我觉得ehcache还是适合一些简单的应用缓存,比如方法级别的,缓存方法的返回值。或者当作一个Map来存储不由GC管理的、可以持久化的数据,比如爬虫url的存储。
- 看着文档学ehcache
- ehcache学习文档
- 【EHCache】EHCache技术文档-下载地址
- 学ARM处理器要看的那些文档(持续整理)
- 我学Hibernate - 08 二级缓存 ehcache
- 看广告,学英文
- 看《后天》,学英语
- 看外国人学汉语
- 看视频,学java
- 《看日记学git》
- 看比较学JAVA
- 看代码学C++
- 看故事,学理财
- 看影视学英语
- 《看漫画》,学 Redux
- 看漫画学 Redux
- 看源码学dagger2
- Ehcache文档_单点登录.doc
- java生成对象的方式
- 框架选型
- sc2017新高二&高一模拟赛4 总结
- linux下用epoll实现的udp服务器例子,很精简和实用
- 获得文件绝对路径的小技巧
- 看着文档学ehcache
- 2017.8.13 总结
- E
- centos安装ansible及其依赖包
- HDU 5839 Special Tetrahedron(几何+暴力)
- 最短路(Bellman队列优化)
- 小型游戏《笑傲江湖之精忠报国》全过程_04
- 每日MySQL之021:EXPLAIN输出中的Join Types
- hdu6103Kirinriki(尺取法)