Memcached客戶端-XMemcached使用

maomao 8年前發布 | 31K 次閱讀 緩存服務器 memcached

來自: http://blog.csdn.net//chenleixing/article/details/47035427


一、 XMemcached 簡介 

XMemcached 是一個新 java memcached client 。也許你還不知道 memcached 是什么?可以先看看這里。簡單來說, Memcached  是一個高性能的分布式內存對象的 key-value 緩存系統,用于動態 Web 應用以減輕數據庫負載,現在也有很多人將它作為內存式數據庫在使用, memcached 通過它的自定義協議與客戶端交互,而XMemcached 就是它的一個 java 客戶端實現。 

二、 使用指南 

2.1  簡單例子 

對于用戶來說,最主要的功能是存取數據,假設我們有一個 memcached 節點 IP 地址或者域名是 host ,端口是 11211 ,一個簡單的存取數據的例子如下: 

  

MemcachedClientBuilder builder = new XMemcachedClientBuilder( 

               AddrUtil.getAddresses (“localhost:11211”)); 

MemcachedClient memcachedClient = builder.build(); 

       try{ 

           memcachedClient. set ( "hello", 0, "Hello,xmemcached"); 

  

           String value = memcachedClient.get ( "hello" ); 

           System. out.println( "hello="+ value); 

  

           memcachedClient. delete ( "hello"); 

           value = memcachedClient.get("hello" ); 

           System. out.println( "hello="+ value); 

  

       } catch(MemcachedException e) { 

           System. err.println( "MemcachedClient operation fail"); 

           e.printStackTrace(); 

       } catch(TimeoutException e) { 

           System. err.println( "MemcachedClient operation timeout"); 

           e.printStackTrace(); 

       } catch(InterruptedException e) { 

           // ignore 

       } 

       try{ 

           memcachedClient.shutdown(); 

       } catch(IOException e) { 

           System. err.println( "Shutdown MemcachedClient fail"); 

           e.printStackTrace(); 

       } 

  

因為 XMemcachedClient 的創建有比較多的可選項,因此提供了一個 XMemcachedClientBuilder 用于構建 MemcachedClient 。 MemcachedClient 是主要接口,操作 memcached 的主要方法都在這個接口里, XMemcachedClient 是它的一個實現。傳入的 memcached 節點列表要求是類似 ”host1:port1 host2:port2 …” 這樣的字符串,通過 AddrUtil.getAddresses 方法獲取實際的 IP 地址列表。存儲數據是通過 set 方法,它有三個參數,第一個是存儲的  key  名稱,第二個是 expire  時間(單位秒)  ,超過這個時間  ,memcached  將這個數據替換出去, 0  表示永久存儲(默認是一個月)  ,第三個參數就是實際存儲的數據,可以是任意的 java  可序列化類型  。 獲取存儲的數據是通過 get 方法,傳入 key 名稱即可。如果要刪除存儲的數據,這是通過 delete 方法,它也是接受 key 名稱作為參數。 XMemcached 由于是基于 nio ,因此通訊過程本身是異步的, client 發送一個請求給 memcached ,你是無法確定 memcached 什么時候返回這個應答,客戶端此時只有等待,因此還有個等待超時的概念在這里。客戶端在發送請求后,開始等待應答,如果超過一定時間就認為操作失敗,這個等待時間默認是一秒,上面例子展現的 3 個方法調用的都是默認的超時時間,這三個方法同樣有允許傳入超時時間的重載方法,例如 

Value=client.get(“hello”,3000); 

  

就是等待 3 秒超時,如果 3 秒超時就跑出 TimeutException ,用戶需要自己處理這個異常。因為等待是通過調用 CountDownLatch.await(timeout) 方法,因此用戶還需要處理中斷異常 InterruptException 。最后的 MemcachedException 表示 Xmemcached 內部發生的異常,如解碼編碼錯誤、網絡斷開等等異常情況。 

  

2.2 CAS 操作 

   Memcached 是通過 cas 協議還實現原子更新,所謂原子更新就是 compare and set ,原理類似樂觀鎖,每次請求存儲某個數據同時要附帶一個 cas 值, memcached 比對這個 cas 值與當前存儲數據的 cas 值是否相等,如果相等就讓新的數據覆蓋老的數據,如果不相等就認為更新失敗,這在并發環境下特別有用。 XMemcached 提供了對 CAS 協議的支持(無論是文本協議還是二進制協議), CAS 協議其實是分為兩個步驟:獲取 CAS 值和嘗試更新,因此一個典型的使用場景如下: 

GetsResponse<Integer> result = client.gets("a" ); 

long cas = result.getCas(); 

if (!client.cas("a" , 0, 2, cas)) { 

       System. err.println( "cas error"); 

} 

  

首先通過 gets 方法獲取一個 GetsResponse ,此對象包裝了存儲的數據和 cas 值,然后通過 cas 方法嘗試原子更新,如果失敗打印”cas error” 。顯然,這樣的方式很繁瑣,并且如果你想嘗試多少次原子更新就需要一個循環來包裝這一段代碼,因此XMemcached 提供了一個CASOpertion 接口包裝了這部分操作,允許你嘗試N 次去原子更新某個 key 存儲的數據,無需顯式地調用 gets 獲取 cas , 上面的代碼簡化為: 

client.cas( "a" , 0, newCASOperation<Integer>() { 

  

              public  int getMaxTries() { 

                  return1; 

              } 

  

              publicInteger getNewValue( longcurrentCAS, Integer currentValue) { 

                  return 2; 

              } 

           }); 

  

CASOpertion 接口只有兩個方法,一個是設置最大嘗試次數的 getMaxTries 方法,這里是嘗試一次,如果嘗試超過這個次數將拋出一個 TimeoutException ,如果你想無限嘗試,可以將返回值設定為 Integer.MAX_VALUE ;另一個方法是根據當前獲得的 GetsResponse 來決定更新數據的 getNewValue 方法,如果更新成功,這個方法返回的值將存儲成功,這個方法的兩個參數是最新一次 gets 返回的 GetsResponse 結果。 

  

2.3  更全面的例子 

  

    一些更全面的例子,展現了 MemcachedClient 接口的主要方法: 

MemcachedClientBuilder builder = new XMemcachedClientBuilder( 

                  AddrUtil.getAddresses (“localhost:12000”)); 

              MemcachedClient client = builder.build(); 

           client.flushAll(); 

if (!client.set("hello" , 0, "world")) { 

              System. err.println( "set error"); 

           } 

           if(client.add( "hello" , 0, "dennis")) { 

              System. err.println( "Add error,key is existed"); 

           } 

           if(!client.replace( "hello" , 0, "dennis")) { 

              System. err.println( "replace error"); 

           } 

           client.append( "hello" , " good"); 

           client.prepend( "hello" , "hello "); 

           String name = client.get("hello" , newStringTranscoder()); 

           System. out.println(name); 

         client.deleteWithNoReply(“hello”); 

  

首先存儲了 hello 對應的 world 字符串,然后調用 add 和 replace 方法去嘗試添加和替換,因為數據已經存在,因此 add 會失敗,同樣 replace 在數據存在的情況才會成功,也就是將 hello 對應的數據更新為 dennis ,然后通過append prepend 方法在 dennis前后加上了字符串 hello good ,因此通過 get 返回的結果是 hello dennis good 。而刪除數據則是通過deleteWithNoReply 方法,這個方法刪除數據并且告訴memcached 不用返回應答 ,因此這個方法不會等待應答直接返回,特別適合于批量處理;同樣地, set 、 add 、 replace 等方法也有相應的withNoReply 重載版本,具體請看 API 文檔。 

  

下面這個例子展現了 incr/decr 操作的使用,兩個操作類似 java 中的原子類如 AtomicIntger ,用于原子遞增或者遞減變量數值: 

assert (1==this .memcachedClient .incr("a" , 5, 1)); 

assert (6==this .memcachedClient .incr("a" , 5)); 

assert (10==this .memcachedClient .incr("a" , 4)); 

assert (9==this .memcachedClient .decr("a" , 1)); 

assert (7==this .memcachedClient .deccr("a" , 2)); 

  

  incr decr 都有三個參數的方法,第一個參數指定遞增的 key 名稱,第二個參數指定遞增的幅度大小,第三個參數指定當 key 不存在的情況下的初始值。兩個參數的重載方法省略了第三個參數,默認指定為 0  

  

Memcached 提供了統計協議用于查看統計信息: 

Map<InetSocketAddress,Map<String,String>> result=client.getStats(); 

  

getStats 方法返回一個map ,其中存儲了所有已經連接并且有效的memcached 節點返回的統計信息,你也可以統計具體的項目,如統計items 項目: 

Map<InetSocketAddress,Map<String,String>> result=client.getStatsByItem(“items”); 

   只要向 getStatsByItem 傳入需要統計的項目名稱即可。 

  

MemcachedClientBuilder builder = new XmemcachedClientBuilder 

(AddrUtil.getAddresses("10.180.44.224:11211 zhouxq:11211"),new int[]{1,3}); 

  

XMemcached 允許通過設置節點的權重來調節memcached 的負載,設置的權重越高,該memcached 節點存儲的數據將越多,所承受的負載越大。 

xmemcached 的權重是通過復制連接的多個引用來實現的,比如權重為 3 ,那么就復制 3 個同一個連接的引用放在集合中讓 MemcachedSessionLocator 查找。 

改變節點權重,可以通過 setServerWeight 方法: 

  public void setServerWeight(String server, int weight); 

weight  與 servers 對應的節點的權重 

weight  可以有也可無 

weight  值大則權重大,否則小 

  

傳入一個 int 數組,里面的元素就是節點對應的權重值,比如這里設置 "10.180.44.224:1121" 節點的權重為 1 ,而 "zhouxq:11211" 的權重為 3 。 

類似的 XMemcachedClient() 和 XMemcachedClientBuilder 相同 

  

設置連接池大小 

     builder.setConnectionPoolSize(5);

 

 本文由用戶 maomao 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!