年关将近,手中的活不是很多,应该是职业病,感觉手闲不下来,想到之前项目中存在的问题,正好有时间一一探索,研究下。
之前项目中用的是ehcache 2.x 版本,与springmvc集成,当时由于是个大型的cdn项目,其中有很大一部分配置信息要快速到达。架构给的建议是要用本地缓存,毕竟网络缓存可能会存在一些未知问题,这也不排除是我们网络太次给我们造成了心里压力的原因。
使用ehcache2.x 的时候也是在网上搜索很多示例,保存到磁盘中,如果服务部署或者宕机等导致tomcat 挂掉后,重启缓存依旧存在,由于配置服务端接口采用的是询问机制,如果不是新的将不会在下发配置数据。所以保存和读取成功则显得非常重要。
ehcache2.x 的相关配置这里就不贴了,咱们直接看ehcache3.x 的使用方式。
其中 ehcache3.x 改观还是比较大的其中:
api的简化,java泛型和使用上的交互
off-head 的使用,以及性能上的优化
其他的版本特性直接去官网看吧 http://www.ehcache.org/resources/
废话不多说,直接上代码!
第一部分 单独测试ehcache3.x 的使用
根据 官网文档 http://www.ehcache.org/documentation/3.4/getting-started.html
ehcache 3.x 构建缓存控制器的方式推荐使用 cacheMangerBuilder 这种方式
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.withCache("preConfigured",
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)))
.build();
// 其中 CacheManagerBuilder.newCacheManagerBuilder().build(true) == cacheManager.init()
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();
磁盘缓存 可以用
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();
这里
persistentCacheManager 接口 继承了 CacheManager 接口 ,而EhcacheManager 是persistentCacheManager 的
实现类 所以 也可以直接声明构建的缓存控制器类型为EhcacheManager
上面是两种方式的基本使用,下面贴出来一些设置
// 缓存的事件监听
CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder
// CacheEventListenerConfiguration使用构建器创建一个指示侦听器和要接收的事件(在这种情况下,创建和更新事件)
.newEventListenerConfiguration(new CacheLogListener(), EventType.CREATED, EventType.UPDATED)
// 可选地指示交付模式 - 默认值是异步的和无序的(出于性能原因)
.unordered().asynchronous();
在使用过程中使用监听器
ListenerObject listener = new ListenerObject();
cache.getRuntimeConfiguration().registerCacheEventListener(listener, EventOrdering.ORDERED,
EventFiring.ASYNCHRONOUS, EnumSet.of(EventType.CREATED, EventType.REMOVED));
// 注销在使用过程中注入的监听器
cache.getRuntimeConfiguration().deregisterCacheEventListener(listener);
//设置缓存键值过期时间
CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.heap(100))
.withExpiry(Expirations.timeToLiveExpiration(Duration.of(20, TimeUnit.SECONDS)))
.build();
//调整可用于传递事件的并发级别
CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.heap(5L))
.withDispatcherConcurrency(10) // 指出所需的并发级别
.withEventListenersThreadPool("listeners-pool").build();
Cache<Long, String> writeBehindCache = cacheManager.createCache("writeBehindCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))
// 配置CacheLoaderWriter
.withLoaderWriter(new SampleLoaderWriter<Long, String>(singletonMap(41L, "zero")))
.add(WriteBehindConfigurationBuilder
// 我们将批量配置为3或最大写入延迟为1秒
.newBatchedWriteBehindConfiguration(1, TimeUnit.SECONDS, 3)
.queueSize(3) // 我们还设置了后写队列的最大大小
.concurrencyLevel(1) // 定义后写队列的并发级别。这表明有多少个写线程并行工作以异步更新记录的底层系统。
.enableCoalescing()) // 启用写入合并行为,这可确保每个批次的每个键只有一个更新到达记录的底层系统。
.build());
线程池的使用:
// CacheManager cacheManager // = CacheManagerBuilder.newCacheManagerBuilder() // .using(PooledExecutionServiceConfigurationBuilder.newPooledExecutionServiceConfigurationBuilder() // .defaultPool("dflt", 0, 10) // .pool("defaultDiskPool", 1, 3) // .pool("cache2Pool", 2, 2) // .build()) // .with(new CacheManagerPersistenceConfiguration(new File(getStoragePath(), "myData"))) // .withDefaultDiskStoreThreadPool("defaultDiskPool") // .withCache("cache1", // CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // ResourcePoolsBuilder.newResourcePoolsBuilder() // .heap(10, EntryUnit.ENTRIES) // .disk(10L, MemoryUnit.MB))) // .withCache("cache2", // CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, // ResourcePoolsBuilder.newResourcePoolsBuilder() // .heap(10, EntryUnit.ENTRIES) // .disk(10L, MemoryUnit.MB)) // .withDiskStoreThreadPool("cache2Pool", 2)) // 告诉缓存为其磁盘存储使用特定的线程池。 // .build(true); // // Cache<Long, String> cache1 = // cacheManager.getCache("cache1", Long.class, String.class); // Cache<Long, String> cache2 = // cacheManager.getCache("cache2", Long.class, String.class); // // cacheManager.close();
上面的特性基本贴完了,接下来给出最终代码
private static String CACHE_NAME = "totalCache"; public static void main(String[] args) throws CachePersistenceException, MalformedURLException { // 缓存的时间监听 CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder // CacheEventListenerConfiguration使用构建器创建一个指示侦听器和要接收的事件(在这种情况下,创建和更新事件) .newEventListenerConfiguration(new CacheLogListener(), EventType.CREATED, EventType.UPDATED) // 可选地指示交付模式 - 默认值是异步的和无序的(出于性能原因) .unordered().asynchronous(); PersistentCacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData"))) .using(PooledExecutionServiceConfigurationBuilder.newPooledExecutionServiceConfigurationBuilder() .pool("defaultEventPool", 1, 3) .pool("cache2Pool", 2, 2) .build()) .withDefaultEventListenersThreadPool("defaultEventPool") .withCache("cache1", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)) .add(CacheEventListenerConfigurationBuilder .newEventListenerConfiguration(new CacheLogListener(), EventType.CREATED, EventType.UPDATED)) .withDispatcherConcurrency(10) // 指出所需的并发级别 .withExpiry(Expirations.timeToLiveExpiration(Duration.of(20, TimeUnit.SECONDS)))) // 设置过期时间 .withCache(CACHE_NAME, CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(10, EntryUnit.ENTRIES) .offheap(1, MemoryUnit.MB) .disk(20, MemoryUnit.MB, true)) .add(cacheEventListenerConfiguration) .withDispatcherConcurrency(10) // 指出所需的并发级别 .withDiskStoreThreadPool("cache2Pool", 2) ).build(true); Cache<Long, String> threeTieredCache =cacheManager.getCache(CACHE_NAME, Long.class, String.class); // threeTieredCache.put(1L, "stillAvailableAfterRestart"); System.out.println("args = [" + threeTieredCache.get(1L) + "]"); cacheManager.close(); }
这里没有涉及集群,序列化,和spring 集成等特性