ehcache簡單使用

轉自 http://oaklet.iteye.com/blog/309037


關於緩存的話題,在罈子裏已經有很多討論,簡單的來說,如果一個應用中80% 的時間內都在訪問20% 的數據,那麼,這時候就應該使用緩存了。 

測試環境: 
MySQL 5.0.22, 
jdk1.6.0_07, 
ehcache-1.6.0-beta2, 
mysql-connector-java-3.1.14 

測試表:
Sql代碼  收藏代碼
  1. CREATE TABLE TEST  
  2. (  
  3. TEST_ID BIGINT,  
  4. TEST_NAME VARCHAR(50),  
  5. TEST_TIME TIMESTAMP,  
  6. TEST_VALUE DECIMAL(10, 3)  
  7. );  

支持類: 
Java代碼  收藏代碼
  1. public class Util {  
  2.   
  3.     public static Random rand = new Random();  
  4.     public static String atoz = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
  5.   
  6.     public static String genString(int length) {  
  7.         StringBuilder re = new StringBuilder(length);  
  8.         re.append(atoz.charAt(rand.nextInt(52)));  
  9.         for (int i = 0; i < length; i++) {  
  10.             re.append(atoz.charAt(rand.nextInt(62)));  
  11.         }  
  12.         return re.toString();  
  13.     }  
  14.   
  15.     public static double genDouble() {  
  16.         double d1 = 5120 * rand.nextDouble();  
  17.         double d2 = 1024000 * rand.nextDouble();  
  18.         return d1 + d2;  
  19.     }  
  20. }  

插入測試數據: 
Java代碼  收藏代碼
  1. public static void traditionalInsert(int total) throws Exception {  
  2.         Thread.sleep(3000);  
  3.         Timestamp current = new Timestamp(System.currentTimeMillis());  
  4.         String currentStr = dateFormat.format(current);  
  5.         System.out.println(currentStr);  
  6.         Connection conn = DriverManager.getConnection(dbURL, user, pass);  
  7.         try {  
  8.             long begin = System.currentTimeMillis();  
  9.             conn.setAutoCommit(false);  
  10.             String sql = "INSERT INTO TEST (TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE) VALUES (?, ?, ?, ?)";  
  11.             PreparedStatement ps = conn.prepareStatement(sql);  
  12.             for (int i = 1; i <= total; i++) {  
  13.                 ps.setLong(1, i);  
  14.                 ps.setString(2, Util.genString(33));  
  15.                 ps.setTimestamp(3, current);  
  16.                 ps.setBigDecimal(4new BigDecimal(Util.genDouble()));  
  17.                 ps.addBatch();  
  18.                 if ((i % 500) == 0) {  
  19.                     ps.executeBatch();  
  20.                 }  
  21.             }  
  22.             ps.executeBatch();  
  23.             conn.commit();  
  24.             long end = System.currentTimeMillis();  
  25.             System.out.printf("Count:%d Time:%d\n", total, (end - begin));  
  26.         } catch (Exception ex) {  
  27.             ex.printStackTrace();  
  28.             conn.rollback();  
  29.         } finally {  
  30.             conn.close();  
  31.         }  
  32.     }  

使用的javaBean: 
Java代碼  收藏代碼
  1. public class TEST implements Serializable {  
  2.     private static final long serialVersionUID = 1L;  
  3.     public Long TEST_ID;  
  4.     public String TEST_NAME;  
  5.     public Timestamp TEST_TIME;  
  6.     public BigDecimal TEST_VALUE;  
  7.     @Override  
  8.     public String toString() {  
  9.         return String.format("ID:%s,,,NAME:%s", TEST_ID, TEST_NAME);  
  10.     }  
  11. }  

先試一下緩存到字典中: 
Java代碼  收藏代碼
  1. public static HashMap<Long, TEST> simpleCache() throws Exception {  
  2.         HashMap<Long, TEST> cacheid = new HashMap<Long, TEST>();  
  3.         Class.forName(dbDriver);  
  4.         Connection conn = DriverManager.getConnection(dbURL, user, pass);  
  5.         try {  
  6.             long begin = System.currentTimeMillis();  
  7.             Statement s = conn.createStatement();  
  8.             String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";  
  9.             ResultSet querySet = s.executeQuery(sql);  
  10.             for (int i = 1; querySet.next(); i++) {  
  11.                 TEST curr = new TEST();  
  12.                 curr.TEST_ID = querySet.getLong(1);  
  13.                 curr.TEST_NAME = querySet.getString(2);  
  14.                 curr.TEST_TIME = querySet.getTimestamp(3);  
  15.                 curr.TEST_VALUE = querySet.getBigDecimal(4);  
  16.                 cacheid.put(curr.TEST_ID, curr);  
  17.             }  
  18.             long end = System.currentTimeMillis();  
  19.             System.out.printf("Time:%d\n", (end - begin));  
  20.         } catch (Exception ex) {  
  21.             ex.printStackTrace();  
  22.         } finally {  
  23.             conn.close();  
  24.         }  
  25.         return cacheid;  
  26.     }  

緩存到字典中,寫法比較簡單,使用方便,缺點就是緩存數據量比較少,一般緩存10W就有可能把jvm的緩存給佔完了。用ehcache就可以解決緩存數據太少的問題。 

一個簡單的配置: 
Xml代碼  收藏代碼
  1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.    xsi:noNamespaceSchemaLocation="ehcache.xsd">  
  3.   <diskStore path="java.io.tmpdir"/>  
  4.   <defaultCache  
  5.     maxElementsInMemory="10000"  
  6.     maxElementsOnDisk="0"  
  7.     eternal="true"  
  8.     overflowToDisk="true"  
  9.     diskPersistent="false"  
  10.     timeToIdleSeconds="0"  
  11.     timeToLiveSeconds="0"  
  12.     diskSpoolBufferSizeMB="50"  
  13.     diskExpiryThreadIntervalSeconds="120"  
  14.     memoryStoreEvictionPolicy="LFU"  
  15.     />  
  16.   <cache name="demoCache"  
  17.     maxElementsInMemory="100"  
  18.     maxElementsOnDisk="0"  
  19.     eternal="false"  
  20.     overflowToDisk="false"  
  21.     diskPersistent="false"  
  22.     timeToIdleSeconds="119"  
  23.     timeToLiveSeconds="119"  
  24.     diskSpoolBufferSizeMB="50"  
  25.     diskExpiryThreadIntervalSeconds="120"  
  26.     memoryStoreEvictionPolicy="FIFO"  
  27.     />  
  28. </ehcache>  

Cache配置中的幾個屬性: 

name:Cache的名稱,必須是唯一的(ehcache會把這個cache放到HashMap裏)。 
maxElementsInMemory:內存中保持的對象數量。 
maxElementsOnDisk:DiskStore中保持的對象數量,默認值爲0,表示不限制。 
eternal:是否是永恆數據,如果是,則它的超時設置會被忽略。 
overflowToDisk:如果內存中數據數量超過maxElementsInMemory限制,是否要緩存到磁盤上。 
timeToIdleSeconds:對象空閒時間,指對象在多長時間沒有被訪問就會失效。只對eternal爲false的有效。默認值0,表示一直可以訪問。 
timeToLiveSeconds:對象存活時間,指對象從創建到失效所需要的時間。只對eternal爲false的有效。默認值0,表示一直可以訪問。 
diskPersistent:是否在磁盤上持久化。指重啓jvm後,數據是否有效。默認爲false。 
diskExpiryThreadIntervalSeconds:對象檢測線程運行時間間隔。標識對象狀態的線程多長時間運行一次。 
diskSpoolBufferSizeMB:DiskStore使用的磁盤大小,默認值30MB。每個cache使用各自的DiskStore。 
memoryStoreEvictionPolicy:如果內存中數據超過內存限制,向磁盤緩存時的策略。默認值LRU,可選FIFO、LFU。 

獲取配置中的demoCache: 
Java代碼  收藏代碼
  1. CacheManager manager = CacheManager.create("ehcache.xml");  
  2. Cache demo = manager.getCache("demoCache");  

往cache中加入數據: 
Java代碼  收藏代碼
  1. public static void ehcache() throws Exception {  
  2.         CacheManager manager = CacheManager.create("ehcache.xml");  
  3.         manager.addCache("TEST_ID.TEST");  
  4.         Cache cid = manager.getCache("TEST_ID.TEST");  
  5.         Class.forName(dbDriver);  
  6.         Connection conn = DriverManager.getConnection(dbURL, user, pass);  
  7.         try {  
  8.             long begin = System.currentTimeMillis();  
  9.             Statement s = conn.createStatement();  
  10.             String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";  
  11.             ResultSet querySet = s.executeQuery(sql);  
  12.             for (int i = 1; querySet.next(); i++) {  
  13.                 TEST curr = new TEST();  
  14.                 curr.TEST_ID = querySet.getLong(1);  
  15.                 curr.TEST_NAME = querySet.getString(2);  
  16.                 curr.TEST_TIME = querySet.getTimestamp(3);  
  17.                 curr.TEST_VALUE = querySet.getBigDecimal(4);  
  18.                 cid.put(new Element(curr.TEST_ID, curr));  
  19.             }  
  20.             long end = System.currentTimeMillis();  
  21.             System.out.printf("Time:%d\n", (end - begin));  
  22.         } catch (Exception ex) {  
  23.             ex.printStackTrace();  
  24.         } finally {  
  25.             conn.close();  
  26.         }  
  27.     }  

這裏在CacheManager中直接加入了一個叫TEST_ID.TEST的cache。因爲只給了一個名字,所以系統會把defaultCache的設置給它clone一份。 
使用方法,像字典一樣使用就行: 
Java代碼  收藏代碼
  1. Cache cid = manager.getCache("TEST_ID.TEST");  
  2. Element e5120 = cid.get(new Long(5120));  
  3. System.out.println(e5120.getValue());  


ehcache中數據是以java對象的形式存在的,使用了java的序列化保存到磁盤,所以保存的對象要實現Serializable接口。ehcache還可以支持分佈式緩存。
發佈了29 篇原創文章 · 獲贊 28 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章