zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Ehcache 3.x 笔记

2023-03-07 09:38:29 时间

现在Ehcache版本已经到3.10了, 网上查到的大部分还是2.x版本的使用说明, 把基础用法记了一下, 以后有时间再翻译.

基础使用, 创建 CacheManager

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() 
    .withCache("preConfigured",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) 
    .build(); 
cacheManager.init(); 

Cache<Long, String> preConfigured =
    cacheManager.getCache("preConfigured", Long.class, String.class); 

Cache<Long, String> myCache = cacheManager.createCache("myCache", 
    CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)));

myCache.put(1L, "da one!"); 
String value = myCache.get(1L); 

cacheManager.removeCache("preConfigured"); 

cacheManager.close();
  1. The static method org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder returns a new org.ehcache.config.builders.CacheManagerBuilder instance.
  2. Use the builder to define a Cache with alias "preConfigured". This cache will be created when cacheManager.build() is invoked on the actual CacheManager instance.
    • The first String argument is the cache alias, which is used to retrieve the cache from the CacheManager.
    • The second argument, org.ehcache.config.CacheConfiguration, is used to configure the Cache. We use the static newCacheConfigurationBuilder() method on org.ehcache.config.builders.CacheConfigurationBuilder to create a default configuration.
  3. Finally, invoking build() returns a fully instantiated, but uninitialized, CacheManager we can use.
  4. Before using the CacheManager it needs to be initialized, which can be done in 1 of 2 ways:
    • Calling CacheManager.init() on the CacheManager instance, or
    • Calling the CacheManagerBuilder.build(boolean init) method with the boolean parameter set to true.
  5. A cache is retrieved by passing its alias, key type and value type to the CacheManager. For instance, to obtain the cache declared in step 2 you need its alias="preConfigured",keyType=Long.class and valueType=String.class. For type-safety, we ask for both key and value types to be passed in. If these differ from the ones we expect, the CacheManager throws a ClassCastException early in the application’s lifecycle. This guards the Cache from being polluted by random types.
  6. The CacheManager can be used to create new Cache instances as needed. Just as in step 2, it requires passing in an alias as well as a CacheConfiguration. The instantiated and fully initialized Cache added will be returned and/or accessed through the CacheManager.getCache API.
  7. The newly added Cache can now be used to store entries, which are comprised of key value pairs. The put method’s first parameter is the key and the second parameter is the value. Remember the key and value types must be the same types as those defined in the CacheConfiguration. Additionally the key must be unique and is only associated with one value.
  8. A value is retrieved from a cache by calling the cache.get(key) method. It only takes one parameter which is the key, and returns the value associated with that key. If there is no value associated with that key then null is returned.
  9. We can CacheManager.removeCache(String) a given Cache. The CacheManager will not only remove its reference to the Cache, but will also close it. The Cache releases all locally held transient resources (such as memory). References to this Cache become unusable.
  10. In order to release all transient resources (memory, threads, …​) a CacheManager provides to Cache instances it manages, you have to invoke CacheManager.close(), which in turns closes all Cache instances known at the time.
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  // A default configuration can be provided at CacheManager level to be used by the caches unless defined explicitly.
  .withDefaultSizeOfMaxObjectSize(500, MemoryUnit.B)
  .withDefaultSizeOfMaxObjectGraph(2000) 
  .withCache("usesConfiguredInCache", usesConfiguredInCacheConfig)
  .withCache("usesDefaultSizeOfEngine", usesDefaultSizeOfEngineConfig)
  .build(true);

创建缓存

// Only 10 entries allowed on heap. Eviction will occur when full.
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES); 
// A shortcut to specify 10 entries.
ResourcePoolsBuilder.heap(10); 
// Only 10 MB allowed. Eviction will occur when full.
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, MemoryUnit.MB); 

For every tier except the heap tier, calculating the size of the cache is fairly easy. You more or less sum the size of all byte buffers containing the serialized entries.
When heap is limited by size instead of entries, it is a bit more complicated. Byte sizing has a runtime performance impact that depends on the size and graph complexity of the data cached.

持久化缓存

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
    .with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData"))) 
    .withCache("threeTieredCache",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
            ResourcePoolsBuilder.newResourcePoolsBuilder()
                .heap(10, EntryUnit.ENTRIES) 
                .offheap(1, MemoryUnit.MB) 
                .disk(20, MemoryUnit.MB, true) 
            )
    ).build(true);

Cache<Long, String> threeTieredCache = persistentCacheManager.getCache("threeTieredCache", Long.class, String.class);
threeTieredCache.put(1L, "stillAvailableAfterRestart"); 

persistentCacheManager.close();
  1. If you wish to use disk storage (like for persistent Cache instances), you’ll have to provide a location where data should be stored on disk to the CacheManagerBuilder.persistence() static method.
  2. You define a resource pool for the heap. This will be your faster but smaller pool.
  3. You define a resource pool for the off-heap. Still pretty fast and a bit bigger.
  4. You define a persistent resource pool for the disk. It is persistent because said it should be (last parameter is true).
  5. All values stored in the cache will be available after a JVM restart (assuming the CacheManager has been closed cleanly by calling close())

缓存过期

CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
        ResourcePoolsBuilder.heap(100))
    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(20))) 
    .build();
  1. Expiry is configured at the cache level, so start by defining a cache configuration,
  2. then add to it an Expiry, here using the predefined time-to-live one, configured with the required Duration

例子

public static void testOffHeapClientClass() {
  CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
    .withClassLoader(TestMethods.class.getClassLoader())
    .withCache("myCache", newCacheConfigurationBuilder(Long.class, Order.class, newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).offheap(2, MemoryUnit.MB))
      .build())
    .build(true);

  Cache<Long, Order> cache = cacheManager.getCache("myCache", Long.class, Order.class);

  Order order = new Order(42L);
  cache.put(42L, order);

  assertTrue(cache.get(42L) instanceof Order);

  cache.replace(42L, order, new Order(-1L));

  assertEquals(-1L, cache.get(42L).id);
}

文档