其他分享
首页 > 其他分享> > ehcache3 分层存储选项

ehcache3 分层存储选项

作者:互联网

参考文档

ehcache3 支持分层存储的概念,本文主要记录不同选项的配置和最佳时间。
当在一个cache中,除了堆这一层外还有其它分层是,会有以下是事情发生。

  1. 在往jvm堆缓存区域外的层写入缓存项时,会有key和value 序列化发生。
  2. 在从jvm堆外缓存区读取缓存项时,会有key、value反序列化发生。
    通过以上两点,我们可以知道数据的二进制形式与序列化的转换方式将对缓存性能有显著的影响。所以需要选择合适的序列化方式。

单一分层设置

所有的分层选项都可以单独使用,如可以只是用堆外内存或集群方式缓存数据。
可用配置如下

单个资源池配置示例

CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // 指定key value 类型
  ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(2, MemoryUnit.GB)).build(); // 指定堆外缓存大小为2GB

堆内缓存层

由于不需要序列化,因此堆内缓存速度更快。也可以使用副本的方式来传递key和value。默认通过引用的方式。
堆内缓存配置如下

// 配置10个entries,超出将出发清除。
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES); 

// or 简短配置 10个 entries
ResourcePoolsBuilder.heap(10); 
// or 指定内存大小配置, 10MB
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, MemoryUnit.MB); 

通过字节大小配置的堆

除了堆这层的缓存,其它缓存层计算缓存大小比较容易。当堆缓存使用基于大小的限制时,计算大小比较复杂。

-- 堆内缓存保存的是被缓存对象的引用,计算大小需要遍历对象引用树来计算大小。

CacheConfiguration<Long, String> usesConfiguredInCacheConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
  ResourcePoolsBuilder.newResourcePoolsBuilder()
    .heap(10, MemoryUnit.KB) //a
    .offheap(10, MemoryUnit.MB)) 
  .withSizeOfMaxObjectGraph(1000)
  .withSizeOfMaxObjectSize(1000, MemoryUnit.B)//c 
  .build();

CacheConfiguration<Long, String> usesDefaultSizeOfEngineConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
  ResourcePoolsBuilder.newResourcePoolsBuilder()
    .heap(10, MemoryUnit.KB))
  .build();

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  .withDefaultSizeOfMaxObjectSize(500, MemoryUnit.B)
  .withDefaultSizeOfMaxObjectGraph(2000) //d
  .withCache("usesConfiguredInCache", usesConfiguredInCacheConfig)
  .withCache("usesDefaultSizeOfEngine", usesDefaultSizeOfEngineConfig)
  .build(true);

堆外内存层-直接内存

ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB);

磁盘存储层

磁盘层,数据保存在磁盘上,因此磁盘越快、越专用,访问缓存数据越快。

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()//1
  .with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData")))//2
  .withCache("persistent-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
    ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB, true))//3
  )
  .build(true);

persistentCacheManager.close();

磁盘层不能在CacheManager 之间共享,一个持久化目录每次只能归属于一个 cache manager。

磁盘层同样需要序列化和反序列化,因此其比堆内和堆外缓存都慢,其使用场景应该如下:

磁盘缓存被分成缓存段,用于提供同步访问。默认为16个segement。可以通过减少segement的个数来减少同步和结束资源。

String storagePath = getStoragePath();
PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  .with(CacheManagerBuilder.persistence(new File(storagePath, "myData")))
  .withCache("less-segments",
    CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
      ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB))
    .withService(new OffHeapDiskStoreConfiguration(2)) 
  )
  .build(true);

persistentCacheManager.close();

集群存储层

。。。

多级缓存设置

若想使用多级缓存,需要遵守以下约束

使用堆内、堆外、集群的示例

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  .with(cluster(CLUSTER_URI).autoCreate(c -> c)) 
  .withCache("threeTierCache",
    CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
      ResourcePoolsBuilder.newResourcePoolsBuilder()
        .heap(10, EntryUnit.ENTRIES) 
        .offheap(1, MemoryUnit.MB) 
        .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)) 
    )
  ).build(true);

资源池

缓存层通过 资源池来配置,简单的方式是ResourcePoolsBuilder。
ResourcePools 资源池一个配置,不实际对于一个缓存资源,不是一个在多个缓存之间共享的内存池。当使用资源池创建缓存时,会根据缓存池创建对应规格的缓存。

ResourcePools pool = ResourcePoolsBuilder.heap(10).build();

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  .withCache("test-cache1", CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, pool))
  .withCache("test-cache2", CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, pool))
  .build(true);

如上, 两个缓存每一个都包含一个10个entries的资源池。而不是共享一个容量为10entries的资源池。

除了集群缓存层

缓存池更新

可以对一个活动的缓存经行容量调整。

updateResourcePools() 只允许调整堆内缓存层大小,不能更改池类型。

ResourcePools pools = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(20L, EntryUnit.ENTRIES).build(); 
cache.getRuntimeConfiguration().updateResourcePools(pools); 
assertThat(cache.getRuntimeConfiguration().getResourcePools()
  .getPoolForResource(ResourceType.Core.HEAP).getSize(), is(20L));

持久层销毁

磁盘和集群层是两种持久层。当想完全移除他们时, PersistentCacheManager 提供以下方法来来完成。
destroy()
该方法会销毁所有和该Manager相关的缓存信息。为了调用该方法,该cache manager处于被关闭或为初始化状态。
destroyCache(String cacheName)
销毁指定的缓存

多层级缓存的操作时序图

多层级缓存的简化帮put和get操作
put操作
使用多层级缓存经行put

get 操作
image


即涉及更新、保存时,最底层之上的缓存层缓存信息都会失效,需要再次查询时,需要从最底层来获取缓存信息,从而将缓存信息从最底层往上一层一层的推。
所有的缓存信息在最底层缓存层都存在,中间层的缓存需要get时,从最底层一步一步往上写。

authoritative 层越慢,写入越慢,对于正常的缓存应用,其实不是个问题,因为get操作比put多得多。若不是该场景,或许第一步就不应该考虑使用缓存。

一个变通的解决方法是细分 cache,通过细粒度的定义cache,来减少cache失效的问题。

标签:10,存储,缓存,MemoryUnit,ResourcePoolsBuilder,ehcache3,分层,heap,class
来源: https://www.cnblogs.com/hhan/p/16638832.html