Memcached學習筆記 - 在JAVA中的應用

最近一直在做一個項目的前期設計工作,考慮到後期系統的擴展和性能問題也找了很多解決方法,有一個就是用到了數據庫的緩存工具memcached(當然該工具並不僅僅侷限於數據庫的緩存)。先簡單的介紹下什麼是memcached。

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

    上網baidu了很多東西,幾乎都差不多,而且基於java的說的很少,所有只有在研究了各個其他語言類的應用後再來嘗試在java上進行簡單的操作應用。先從memcached上進行說明,memcached的最新版是採用c語言進行開發和設計的,據說舊版的是採用perl語言開發的,而且它是一個應用軟件來的,是作爲緩存服務器的服務器端運行在服務器上的,需要使用特定的語言編寫客戶端與其進行通信來進行數據的緩存和獲取。通常我們是把memcached安裝運行在web服務器上,然後通過對需要的數據進行緩存,據我目前所知,所有數據的緩存設置和存取操作,以及數據的更新後替換操作全部需要程序來進行,而不是自動進行的(自動不知道能不能成功,呵呵)。下面從一個實際的例子來應用memcached。

    首先到http://danga.com/memcached/下載memcached的windows版本和java客戶端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分別解壓後即可!首先是安裝運行memcached服務器,我們將memcached-1.2.1-win32.zip解壓後,進入其目錄,然後運行如下命令:

c:>memcached.exe -d install
c:>memcached.exe -l 127.0.0.1 -m 32 -d start

    第一行是安裝memcached成爲服務,這樣才能正常運行,否則運行失敗!第一行是啓動memcached的,作爲測試我們就簡單的只分配32M內存了,然後監聽本機端口和以守護進行運行。執行完畢後,我們就可以在任務管理器中見到memcached.exe這個進程了。好了,我們的服務器已經正常運行了, 下面我們就來寫java的客戶端連接程序。

    我們將java_memcached-release_1.6.zip解壓後的目錄中的java_memcached-release_1.6.jar文件複製到java項目的lib目錄下,然後我們來編寫代碼,比如我提供的一個應用類如下:

package utils.cache;

import java.util.Date;

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


/**
* 使用memcached的緩存實用類.
*
*
@author 鐵木箱子
*
*/
public class MemCached
{
   
// 創建全局的唯一實例
    protected static MemCachedClient mcc = new MemCachedClient();
   
   
protected static MemCached memCached = new MemCached();
   
   
// 設置與緩存服務器的連接池
    static {
       
// 服務器列表和其權重
        String[] servers = {"127.0.0.1:11211"};
        Integer[] weights
= {3};

       
// 獲取socke連接池的實例對象
        SockIOPool pool = SockIOPool.getInstance();

       
// 設置服務器信息
        pool.setServers( servers );
        pool.setWeights( weights );

       
// 設置初始連接數、最小和最大連接數以及最大處理時間
        pool.setInitConn( 5 );
        pool.setMinConn(
5 );
        pool.setMaxConn(
250 );
        pool.setMaxIdle(
1000 * 60 * 60 * 6 );

       
// 設置主線程的睡眠時間
        pool.setMaintSleep( 30 );

       
// 設置TCP的參數,連接超時等
        pool.setNagle( false );
        pool.setSocketTO(
3000 );
        pool.setSocketConnectTO(
0 );

       
// 初始化連接池
        pool.initialize();

       
// 壓縮設置,超過指定大小(單位爲K)的數據都會被壓縮
        mcc.setCompressEnable( true );
        mcc.setCompressThreshold(
64 * 1024 );
    }
   
   
/**
     * 保護型構造方法,不允許實例化!
     *
    
*/
   
protected MemCached()
    {
       
    }
   
   
/**
     * 獲取唯一實例.
     *
@return
    
*/
   
public static MemCached getInstance()
    {
       
return memCached;
    }
   
   
/**
     * 添加一個指定的值到緩存中.
     *
@param key
     *
@param value
     *
@return
    
*/
   
public boolean add(String key, Object value)
    {
       
return mcc.add(key, value);
    }
   
   
public boolean add(String key, Object value, Date expiry)
    {
       
return mcc.add(key, value, expiry);
    }
   
   
public boolean replace(String key, Object value)
    {
       
return mcc.replace(key, value);
    }
   
   
public boolean replace(String key, Object value, Date expiry)
    {
       
return mcc.replace(key, value, expiry);
    }
   
   
/**
     * 根據指定的關鍵字獲取對象.
     *
@param key
     *
@return
    
*/
   
public Object get(String key)
    {
       
return mcc.get(key);
    }
   
   
public static void main(String[] args)
    {
        MemCached cache
= MemCached.getInstance();
        cache.add(
"hello", 234);
        System.out.print(
"get value : " + cache.get("hello"));
    }
}

    那麼我們就可以通過簡單的像main方法中操作的一樣存入一個變量,然後再取出進行查看,我們可以看到先調用了add,然後再進行get,我們運行一次後,234這個值已經被我們存入了memcached的緩存中的了,我們將main方法中紅色的那一行註釋掉後,我們再運行還是可以看到get到的value也是234,即緩存中我們已經存在了數據了。

    對基本的數據我們可以操作,對於普通的POJO而言,如果要進行存儲的話,那麼比如讓其實現java.io.Serializable接口,因爲memcached是一個分佈式的緩存服務器,多臺服務器間進行數據共享需要將對象序列化的,所以必須實現該接口,否則會報錯的。比如我們寫一個簡單的測試Bean如下:

class TBean implements java.io.Serializable
{
   
private static final long serialVersionUID = 1945562032261336919L;
   
   
private String name;

   
public String getName()
    {
       
return name;
    }

   
public void setName(String name)
    {
       
this.name = name;
    }
}

    然後我們在main方法中加入如下幾行代碼:

TBean tb = new TBean();
tb.setName(
"鐵木箱子");
cache.add(
"bean", tb);
TBean tb1
= (TBean)cache.get("bean");
System.out.print(
"name=" + tb1.getName());
tb1.setName(
"鐵木箱子_修改的");
tb1
= (TBean)cache.get("bean");
System.out.print(
"name=" + tb1.getName());

    我們首先把TBean的一個實例放入緩存中,然後再取出來,並進行名稱的修改,然後我們再取這個對象,我們再看其名稱,發現修改的對象並不是緩存中的對象,而是通過序列化過來的一個實例對象,這樣我們就無須擔心對原生類的無意修改導致緩存數據失效了,呵呵~~看來我也是多此一想啊。所以這表明從緩存中獲取的對象是存入對象的一個副本,對獲取對象的修改並不能真正的修改緩存中的數據,而應該使用其提供的replace等方法來進行修改。

    以上是我在windows下對memcached的一點小學習和實踐,在以後的項目開發過程中將會更深入的學習和應用這一緩存工具,也希望和有興趣的同行一起討論學習該工具的使用~~ 微笑

發佈了18 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章