天天看點

探索使用Ehcache 3.x

年關将近,手中的活不是很多,應該是職業病,感覺手閑不下來,想到之前項目中存在的問題,正好有時間一一探索,研究下。

之前項目中用的是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 內建等特性

繼續閱讀