0


【精品】JDK17下使用Ehcache3

Ehcache简介

Ehcache 是一个开源的高性能缓存,拥有很高的拓展性和伸缩性,广泛使用各种 Java 项目中(如 Hibernate 默认使用 Ehcache作为二级缓存),在目前基于 Java 的缓存方案里,几乎是性能最高的实现。

Ehcache 官网:http://www.ehcache.org
Ehcache 3.X 技术文档:http://www.ehcache.org/documentation/

Ehcache架构:在这里插入图片描述
Ehcache的特点:

  • 缓存数据有三级:内存、堆外缓存Off-Heap、Disk缓存,因此无需担心容量问题。还可以通过RMI、可插入API等方式进行分布式缓存。
  • 缓存数据会在虚拟机重启的过程中写入磁盘,持久化。
  • 具有缓存和缓存管理器的侦听接口。
  • 支持多缓存管理器实例,以及一个实例的多个缓存区域。

Ehcache3支持堆、堆外、磁盘以及集群缓存;除了堆之外的三种缓存,缓存的键值对必须支持序列化和反序列化。我们在使用的时候,可以单独使用任意一个。

  • heap :堆上存储,利用Java的堆上RAM内存来存储缓存条目。该层使用与Java应用程序相同的堆内存
  • off-heap: 堆外内存,大小仅受可用RAM限制。不受Java垃圾回收(GC)的约束。与堆上存储相比,它速度较慢,因为在存储和重新访问JVM堆时必须将数据移入和移出JVM堆。
  • disk:利用磁盘(文件系统)存储缓存条目。存储空间充足,但比基于RAM的存储要慢得多。对于所有使用磁盘存储的应用程序,建议使用快速专用磁盘来优化吞吐量。
  • clustered:群集存储,该数据存储是远程服务器上的缓存。

使用

  • 常被查询、最重要、数据量较小的数据存放在堆缓存,不用担心JVM的重启,有持久化机制;
  • 常被查询、数据量中等的数据存放在堆外缓存,几个G就好了,不用担心服务器的重启,有持久化机制;
  • 不常用、大量的数据、但又不想占用数据库IO的数据,放在Disk缓存,容量自便;

如果要使用多个层,则必须遵守一些约束条件:

  • 必须始终有堆内存
  • disk和clusterd不能同时存在
  • 层的大小应采用金字塔式的大小,即,金字塔较高的层配置为使用的内存比下方较低的层少。

可能出现的层组合:

  • heap + offheap
  • heap + offheap + disk
  • heap + offheap + clustered
  • heap + disk
  • heap + clustered

注意:

  • 将值放入高速缓存时,它会直接进入最低层,比如heap + offheap + disk直接会存储在disk层。
  • 当获取一个值,从最高层获取,如果没有继续向下一层获取,一旦获取到,会向上层推送,同时上层存储该值。
    小知识:堆外缓存堆外缓存(off-heap)既是独立的进程缓存,又是JVM堆外的系统缓存。JVM堆是非常宝贵的,如果占用过大会带来GC性能问题,堆外缓存很好的解决了这个问题。现在服务器内存越来越大,而磁盘缓存的io性能又比较低,off-heap缓存就是折中的方案,既保证了高速性能,又可以有一定的容量。off-heap缓存性能的占用主要是序列化、反序列化的过程。一旦对象被序列化,在返回Java堆的时候必需反序列化才可以使用。这是一笔较大的性能开销。但off-heap还是要比本地磁盘、网络存储、RDBMS数据库IO等记录数据的系统要快的多。还应指出的是,序列化/反序列化的性能开销远没有很多用户想象的那么大。off-heap已经针对字节缓冲区做了优化,本身也包含一些优化机制,可以对使用标准Java序列化的对象进行优化,能使复杂Java对象的性能提升两倍,使byte数组的性能提升四倍。

    示例

备注:由于JDK17的原因,xml配置方式使用Ehcache会报各种莫名其妙的问题,基本上没有研究的意义,所以下面示例只讲了Java代码的方式。

Maven依赖:

<dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.10.0</version></dependency><dependency><groupId>javax.cache</groupId><artifactId>cache-api</artifactId><version>1.1.1</version></dependency>

测试代码一:创建CacheManager的同时指定Cache

@Testpublicvoidfun1(){CacheManager manager =CacheManagerBuilder.newCacheManagerBuilder().withCache("myCache",CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class,String.class,ResourcePoolsBuilder.heap(100).build())).build(true);//通过别名获取缓存Cache<Integer,String> cache = manager.getCache("myCache",Integer.class,String.class);

    cache.put(1001,"haha");String value = cache.get(1001);System.out.println(value);// 移除一个给定的Cache,CacheManager不仅会删除它对Cache的引用,而且还会关闭它。
    manager.removeCache("myCache");// 关闭CacheManager提供的所有临时资源。
    manager.close();}

在cacheManager中检索Cache,需要通过别名、键类型,值类型。比如,要获得第2步中声明的缓存,您需要它的别名=“myCache”,keyType=Integer.class和valueType = String.class。出于类型安全考虑,我们要求键和值类型都要传递。如果这些和我们期望的不同CacheManager将会在应用程序生命周期的早期抛出一个ClassCastException这可以保护缓存免受随机类型的污染。
put()方法用来往Cache中添加内容,其中:第一个参数是键,第二个参数是值。键和值类型必须是与在cacheconfig容器中定义的类型相同的类型。另外,键必须是惟一的,并且只与一个值相关联。
get(key)方法用来从缓存中检索值。它只需要一个参数,这个参数是键,然后返回与该键关联的值。如果没有与该键相关联的值,则返回null。

测试代码二:

@Testpublicvoidfun2(){CacheManager manager =CacheManagerBuilder.newCacheManagerBuilder().build(true);//创建Cache实例CacheConfigurationBuilder<Integer,String> builder =CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class,String.class,ResourcePoolsBuilder.heap(10)//堆内缓存,速度最快.offheap(2,MemoryUnit.MB)// 堆外内存,速度低于 heap,但是高于 disk// .disk(1, MemoryUnit.GB)   //磁盘缓存,速度最低,相对于 heap和off-heap,disk可以分配大量资源空间).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(10)));Cache<Integer,String> cache = manager.createCache("myCache", builder);//写缓存
    cache.put(1001,"xixi");//读缓存String value = cache.get(1001);System.out.println(value);

    manager.removeCache("myCache");//关闭资源
    manager.close();}

测试代码三:将数据缓存到本地硬盘上

@Testpublicvoidfun4(){CacheManager manager =CacheManagerBuilder.persistence("d:/CacheData")//硬盘缓存文件位置.builder(CacheManagerBuilder.newCacheManagerBuilder()).build();
    manager.init();//创建Cache实例CacheConfigurationBuilder<Integer,String> builder =CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class,String.class,ResourcePoolsBuilder.heap(10));Cache<Integer,String> cache = manager.createCache("myCache", builder);//写缓存
    cache.put(1001,"xixi");//读缓存String value = cache.get(1001);System.out.println(value);

    manager.removeCache("myCache");//关闭资源
    manager.close();}

测试代码四:

@Testpublicvoidfun3(){UserManagedCache<Integer,String> cache =UserManagedCacheBuilder.newUserManagedCacheBuilder(Integer.class,String.class).build(false);
    cache.init();//写
    cache.put(11,"aa");//读String value = cache.get(11);System.out.println(value);

    cache.close();}
标签: Ehcache3

本文转载自: https://blog.csdn.net/lianghecai52171314/article/details/124419796
版权归原作者 梁云亮 所有, 如有侵权,请联系我们删除。

“【精品】JDK17下使用Ehcache3”的评论:

还没有评论