(轉)java中使用memcache

背景:公司項目中使用java和memcache相結合來搭建緩存,因此要了解下緩存的基礎知識!java

1 瞭解memcache

1.1 基礎知識

什麼是Memcache?mysql

Memcache集羣環境下緩存解決方案linux

Memcache是一個高性能的分佈式的內存對象緩存系統,經過在內存裏維護一個統一的巨大的hash表,它可以用來存儲各類格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。簡單的說就是將數據調用到內存中,而後從內存中讀取,從而大大提升讀取速度。  spring

Memcache是danga的一個項目,最先是LiveJournal 服務的,最初爲了加速 LiveJournal 訪問速度而開發的,後來被不少大型的網站採用。  sql

Memcached是以守護程序方式運行於一個或多個服務器中,隨時會接收客戶端的鏈接和操做數據庫

 

爲何會有Memcache和memcached兩種名稱?

其實Memcache是這個項目的名稱,而memcached是它服務器端的主程序文件名,知道個人意思了吧。一個是項目名稱,一個是主程序文件名,在網上看到了不少人不明白,因而混用了。apache


Memcached是高性能的,分佈式的內存對象緩存系統,用於在動態應用中減小數據庫負載,提高訪問速度。Memcached由Danga Interactive開發,用於提高LiveJournal.com訪問速度的。LJ每秒動態頁面訪問量幾千次,用戶700萬。Memcached將數據庫負載大幅度下降,更好的分配資源,更快速訪問。windows

1.2 linux服務器使用說明

Windows下的Memcache安裝api

1.  安裝緩存

在這裏簡單介紹一下Windows下的Memcache的安裝:

1. 下載memcache的windows穩定版,解壓放某個盤下面,好比在c:\memcached

2. 在終端(也即cmd命令界面)下輸入‘c:\memcached\memcached.exe -d install’安裝

3. 再輸入:‘c:\memcached\memcached.exe -d start’啓動。NOTE: 之後memcached將做爲windows的一個服務每次開機時自動啓動。這樣服務器端已經安裝完畢了。

2. memcached的基本設置

-p 監聽的端口

-l 鏈接的IP地址, 默認是本機

-d start 啓動memcached服務

-d restart 重起memcached服務

-d stop|shutdown 關閉正在運行的memcached服務

-d install 安裝memcached服務

-d uninstall 卸載memcached服務

-u 以的身份運行 (僅在以root運行的時候有效)

-m 最大內存使用,單位MB。默認64MB

-M 內存耗盡時返回錯誤,而不是刪除項

-c 最大同時鏈接數,默認是1024

-f 塊大小增加因子,默認是1.25

-n 最小分配空間,key+value+flags默認是48

-h 顯示幫助

3.  設置Memcache緩存大小和端口

Memcache的默認啓動時的參數可能不知足實際生產環境的須要,因而就想到直接修改windows服務的啓動參數,操做以下:

打開註冊表,找到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\memcached Server

其中的ImagePath項的值爲: c:\memcached\memcached.exe" -d runservice

改爲:c:\memcached\memcached.exe" -p 12345 -m 128 -d runservice

其中,-p就是端口,-m就是緩存大小,以M爲單位。

linux下的Memcache安裝

1)安裝Memcache服務端

sudo apt-get install memcached

安裝完Memcache服務端之後,咱們須要啓動該服務:

memcached -d -m 128 -p 11111 -u root

這裏須要說明一下memcached服務的啓動參數:

-p 監聽的端口
-l 鏈接的IP地址, 默認是本機 -d start 啓動memcached服務 -d restart 重起memcached服務 -d stop|shutdown 關閉正在運行的memcached服務 -d install 安裝memcached服務 -d uninstall 卸載memcached服務 -u 以的身份運行 (僅在以root運行的時候有效) -m 最大內存使用,單位MB。默認64MB -M 內存耗盡時返回錯誤,而不是刪除項 -c 最大同時鏈接數,默認是1024 -f 塊大小增加因子,默認是1.25-n 最小分配空間,key+value+flags默認是48 -h 顯示幫助

 

查看是否創建成功

telnet測試memcached
telnet 192.168.1.2 11211

Trying 192.168.1.2...
Connected to 192.168.1.2.
Escape character is '^]'

查看版本

version

對Memcached緩存服務的狀態查詢,能夠先telnet鏈接上服務:telnet 127.0.0.1 11211 ,而後使用 stats命令查看緩存服務的狀態,會返回以下的數據:    

     time:    1255537291                               服務器當前的unix時間戳 
        total_items:    54 從服務器啓動之後存儲的items總數量 connection_structures: 19 服務器分配的鏈接構造數 version: 1.2.6 memcache版本 limit_maxbytes: 67108864 分配給memcache的內存大小(字節) cmd_get: 1645 get命令(獲取)總請求次數 evictions: 0 爲獲取空閒內存而刪除的items數(分配給memcache的空間用滿後需 要刪除舊的items來獲得空間分配給新的items) total_connections: 19 從服務器啓動之後曾經打開過的鏈接數 bytes: 248723 當前服務器存儲items佔用的字節數 threads: 1 當前線程數 get_misses: 82 總未命中次數 pointer_size: 32 當前操做系統的指針大小(32位系統通常是32bit) bytes_read: 490982 總讀取字節數(請求字節數) uptime: 161 服務器已經運行的秒數 curr_connections: 18 當前打開着的鏈接數 pid: 2816 memcache服務器的進程ID bytes_written: 16517259 總髮送字節數(結果字節數) get_hits: 1563 總命中次數 cmd_set: 54 set命令(保存)總請求次數 curr_items: 28 服務器當前存儲的items數量

 

ps:windows下一樣能夠。

 

Ok,安裝memcached1.4.5成功。

1.3 數據讀寫測試

一些memcache相關命令能夠慢慢搜索積累。

[root@odb ~]# telnet 127.0.0.1 10000

Trying 127.0.0.1…

Connected to localhost.localdomain (127.0.0.1).

Escape character is ‘^]’.

set key 0 0 8                       <—在10000端口設置key的值

88888888

STORED

quit

Connection closed by foreign host.

 

[root@odb ~]# telnet 127.0.0.1 11211

Trying 127.0.0.1…

Connected to localhost.localdomain (127.0.0.1).

Escape character is ‘^]’.

get key                     <—在11211端口獲取key的值成功

VALUE key 0 8

88888888

END

quit

Connection closed by foreign host.

 

[root@odb ~]# telnet 127.0.0.1 11212

Trying 127.0.0.1…

Connected to localhost.localdomain (127.0.0.1).

Escape character is ‘^]’.

get key                     <—在11212端口獲取key的值成功

VALUE key 0 8

88888888

END

quit

Connection closed by foreign host.

 

2 在java中使用memcache

2.1 基本使用方法

初始化memcache:

static {  
        String[] serverlist = { "server1.com:port", "server2.com:port" }; SockIOPool pool = SockIOPool.getInstance(); pool.setServers(serverlist); pool.initialize(); } 

 

建立一個client對象:

MemCachedClient mc = new MemCachedClient();  

建立一個緩存:

MemCachedClient mc = new MemCachedClient();  
 String key = "cacheKey1"; Object value = SomeClass.getObject(); mc.set(key, value); 

經過key刪除一個緩存:

MemCachedClient mc = new MemCachedClient();  
 String key = "cacheKey1"; mc.delete(key); 

經過key獲取緩存對象:

MemCachedClient mc = new MemCachedClient();  
 String key = "key"; Object value = mc.get(key);

獲取多個緩存對象:

MemCachedClient mc = new MemCachedClient();  
 String[] keys = { "key", "key1", "key2" }; Map<Object> values = mc.getMulti(keys); 

刷新所有緩存: 

MemCachedClient mc = new MemCachedClient();  
 mc.flushAll(); 

 2.2 memcache客戶端程序

Memcached的java客戶端已經存在三種了:

  官方提供的基於傳統阻塞io由Greg Whalin維護的客戶端

  Dustin Sallings實現的基於Java nio的Spymemcached

  XMemcached

1. 三種API比較 

1)  memcached client for java

較早推出的memcached JAVA客戶端API,應用普遍,運行比較穩定。

 

2) spymemcached

A simple, asynchronous, single-threaded memcached client written in java. 支持異步,單線程的memcached客戶端,用到了java1.5版本的concurrent和nio,存取速度會高於前者,可是穩定性很差,測試中常報timeOut等相關異常。


3)  xmemcached

XMemcached一樣是基於java nio的客戶端,java nio相比於傳統阻塞io模型來講,有效率高(特別在高併發下)和資源耗費相對較少的優勢。傳統阻塞IO爲了提升效率,須要建立必定數量的鏈接造成鏈接池,而nio僅須要一個鏈接便可(固然,nio也是能夠作池化處理),相對來講減小了線程建立和切換的開銷,這一點在高併發下特別明顯。所以XMemcached與Spymemcached在性能都很是優秀,在某些方面(存儲的數據比較小的狀況下)Xmemcached比Spymemcached的表現更爲優秀,具體能夠看這個Java Memcached Clients Benchmark。


2. 建議

因爲memcached client for java發佈了新版本,性能上有所提升,而且運行穩定,因此建議使用memcached client for java。

XMemcached也使用得比較普遍,並且有較詳細的中文API文檔,具備以下特色:高性能、支持完整的協議、支持客戶端分佈、容許設置節點權重、動態增刪節點、支持JMX、與spring框架和hibernate-memcached的集成、客戶端鏈接池、可擴展性好等。

下面給出這三種客戶端的示例程序。

2.3 三種api的示例程序

1)     memcached client for java

從前面介紹的Java環境的Memcached客戶端程序項目網址裏,下載最新版的客戶端程序包:java_memcached-release_2.5.1.zip,解壓後,文件夾裏找到java_memcached-release_2.5.1.jar,這個就是客戶端的JAR包。將此JAR包添加到項目的構建路徑裏,則項目中,就可使用Memcached了。

示例代碼以下:

package temp;
 
import com.danga.MemCached.*;
import org.apache.log4j.*;
 
public class CacheTest {
    public static void main(String[] args) {
       /**
        * 初始化SockIOPool,管理memcached的鏈接池
        * */
       String[] servers = { "10.11.15.222:10000" };
       SockIOPool pool = SockIOPool.getInstance();
       pool.setServers(servers);
       pool.setFailover(true);
       pool.setInitConn(10);
       pool.setMinConn(5);
       pool.setMaxConn(250);
       pool.setMaintSleep(30);
       pool.setNagle(false);
       pool.setSocketTO(3000);
       pool.setAliveCheck(true);
       pool.initialize();
      
       /**
        * 創建MemcachedClient實例
        * */
       MemCachedClient memCachedClient = new MemCachedClient();
       for (int i = 0; i < 1000; i++) {
           /**
            * 將對象加入到memcached緩存
            * */
           boolean success = memCachedClient.set("" + i, "Hello!");
           /**
            * 從memcached緩存中按key值取對象
            * */
           String result = (String) memCachedClient.get("" + i);
           System.out.println(String.format("set( %d ): %s", i, success));
           System.out.println(String.format("get( %d ): %s", i, result));
       }
    }
}

2)      spymemcached

spymemcached當前版本是2.5版本,官方網址是:http://code.google.com/p/spymemcached/。能夠從地址:http://spymemcached.googlecode.com/files/memcached-2.5.jar下載最新版原本使用。

示例代碼以下:

package temp;
 
import java.NET.InetSocketAddress;
import java.util.concurrent.Future;
 
import net.spy.memcached.MemcachedClient;
 
public class TestSpyMemcache {
    public static void main(String[] args) {
       // 保存對象
       try {
           /* 創建MemcachedClient 實例,並指定memcached服務的IP地址和端口號 */
           MemcachedClient mc = new MemcachedClient(new InetSocketAddress("10.11.15.222", 10000));
           Future<Boolean> b = null;
           /* 將key值,過時時間(秒)和要緩存的對象set到memcached中 */
           b = mc.set("neea:testDaF:ksIdno", 900, "someObject");
           if (b.get().booleanValue() == true) {
              mc.shutdown();
           }
       } catch (Exception ex) {
           ex.printStackTrace();
       }
       // 取得對象
        try {
           /* 創建MemcachedClient 實例,並指定memcached服務的IP地址和端口號 */
           MemcachedClient mc = new MemcachedClient(new InetSocketAddress("10.11.15.222", 10000));
           /* 按照key值從memcached中查找緩存,不存在則返回null */
           Object b = mc.get("neea:testDaF:ksIdno");
           System.out.println(b.toString());
           mc.shutdown();
       } catch (Exception ex) {
           ex.printStackTrace();
       }
    }
}

3)      xmemcached

Xmemcached的官方網址是:http://code.google.com/p/xmemcached/,能夠從其官網上下載最新版本的1.2.4來使用。地址是:http://xmemcached.googlecode.com/files/xmemcached-1.2.4-src.tar.gz

示例代碼以下:

package temp;
 
import java.io.IOException;
import java.util.concurrent.TimeoutException;
 
import net.rubyeye.xmemcached.utils.AddrUtil;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.exception.MemcachedException;
 
public class TestXMemcache {
    public static void main(String[] args) {
       MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil
              .getAddresses("10.11.15.222:10000"));
       MemcachedClient memcachedClient;
       try {
           memcachedClient = builder.build();
      
           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);
           // close memcached client
           memcachedClient.shutdown();
       } 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
       }catch (IOException e) {
           System.err.println("Shutdown MemcachedClient fail");
           e.printStackTrace();
       }
    }
}
相關文章
相關標籤/搜索