Memcache工作原理及其例子
Memcache是danga.com的一個專案,最早是為 LiveJournal 服務的,目前全世界不少人使用這個快取專案來構建自己大負載的網站,來分擔資料庫的壓力。
它可以應對任意多個連線,使用非阻塞的網路IO。由於它的工作機制是在記憶體中開闢一塊空間,然後建立一個HashTable,Memcached自管理這些HashTable。
為什麼會有Memcache和memcached兩種名稱?
其實Memcache是這個專案的名稱,而memcached是它伺服器端的主程式檔名,
2 Memcache工作原理
首先 memcached 是以守護程式方式運行於一個或多個伺服器中,隨時接受客戶端的連線操作,客戶端可以由各種語言編寫,目前已知的客戶端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客戶端在與 memcached 服務建立連線之後,接下來的事情就是存取物件了,每個被存取的物件都有一個唯一的識別符號 key,存取操作均通過這個 key 進行,儲存到memcached 中的物件實際上是放置記憶體中的,並不是儲存在 cache 檔案中的,這也是為什麼 memcached 能夠如此高效快速的原因。注意,這些物件並不是持久的,服務停止之後,裡邊的資料就會丟失。
與許多 cache 工具類似,Memcached 的原理並不複雜。它採用了C/S的模式,在 server 端啟動服務程序,在啟動時可以指定監聽的 ip,自己的埠號,所使用的記憶體大小等幾個關鍵引數。一旦啟動,服務就一直處於可用狀態。Memcached 的目前版本是通過C實現,採用了單程序,單執行緒,非同步I/O,基於事件 (event_based) 的服務方式.使用libevent 作為事件通知實現。多個 Server 可以協同工作,但這些 Server 之間是沒有任何通訊聯絡的,每個 Server 只是對自己的資料進行管理。Client 端通過指定 Server 端的 ip 地址(通過域名應該也可以)。需要快取的物件或資料是以 key->value對的形式儲存在Server端。key 的值通過 hash 進行轉換,根據 hash 值把 value 傳遞到對應的具體的某個 Server 上。當需要獲取物件資料時,也根據 key 進行。首先對 key 進行 hash,通過獲得的值可以確定它被儲存在了哪臺 Server 上,然後再向該 Server 發出請求。Client 端只需要知道儲存 hash(key) 的值在哪臺伺服器上就可以了。
其實說到底,memcache 的工作就是在專門的機器的記憶體裡維護一張巨大的 hash 表,來儲存經常被讀寫的一些陣列與檔案,從而極大的提高網站的執行效率。
3 如何使用
-
建立Manager類
package com.alisoft.sme.memcached; import java.util.Date; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; public class MemCachedManager { // 建立全域性的唯一例項 protected static MemCachedClient mcc = new MemCachedClient(); protected static MemCachedManager memCachedManager = new MemCachedManager(); // 設定與快取伺服器的連線池 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 MemCachedManager() { } /** * 獲取唯一例項. * * @return */ public static MemCachedManager getInstance() { return memCachedManager; } /** * 新增一個指定的值到快取中. * * @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) { MemCachedManager cache = MemCachedManager.getInstance(); cache.add("hello", 234); System.out.print("get value : " + cache.get("hello")); } }
建立資料物件
建立資料物件
package com.alisoft.sme.memcached;
import java.io.Serializable;
public class TBean implements Serializable {
private static final long serialVersionUID = 1945562032261336919L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
建立測試用例
package com.alisoft.sme.memcached.test;
import junit.framework.TestCase;
import org.junit.Test;
import com.alisoft.sme.memcached.MemCachedManager;
import com.alisoft.sme.memcached.TBean;
public class TestMemcached extends TestCase {
private static MemCachedManager cache;
@Test
public void testCache() {
TBean tb = new TBean();
tb.setName("E網打進");
cache.add("bean", tb);
TBean tb1 = (TBean) cache.get("bean");
System.out.println("name=" + tb1.getName());
tb1.setName("E網打進_修改的");
tb1 = (TBean) cache.get("bean");
System.out.println("name=" + tb1.getName());
}
@Override
protected void setUp() throws Exception {
super.setUp();
cache = MemCachedManager.getInstance();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
cache = null;
}
}
測試結果
[INFO] ++++ serializing for key: bean for class: com.alisoft.sme.memcached.TBean
[INFO] ++++ memcache cmd (result code): add bean 8 0 93 (NOT_STORED)
[INFO] ++++ data not stored in cache for key: bean
[INFO] ++++ deserializing class com.alisoft.sme.memcached.TBean
name=E網打進
[INFO] ++++ deserializing class com.alisoft.sme.memcached.TBean
name=E網打進