Memcached學習筆記之二:入門使用
使用
現在伺服器已經正常運行了,下面我們就來寫java的客戶端連線程式。
將java_memcached-release.zip解壓,把java_memcached-release.jar檔案複製到java專案的lib目錄下,
然後我們來編寫程式碼,比如我提供的一個應用類如下:
package memcached.test; import java.util.Date; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; /** * 使用memcached的快取實用類. */ 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連線池的例項物件 // 這個類用來建立管理客戶端和伺服器通訊連線池, // 客戶端主要的工作(包括資料通訊、伺服器定位、hash碼生成等)都是由這個類完成的。 SockIOPool pool = SockIOPool.getInstance(); // 設定伺服器資訊 pool.setServers(servers); // 設定Server權重 pool.setWeights(weights); // 設定初始連線數、最小和最大連線數以及最大處理時間 pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(250); pool.setMaxIdle(1000 * 60 * 60 * 6); // 設定主執行緒的睡眠時間 pool.setMaintSleep(30); // 設定連線心跳監測開關 // true:每次通訊都要進行連線是否有效的監測,造成通訊次數倍增,加大網路負載, // 因此在對HighAvailability要求比較高的場合應該設為true // 預設狀態是false,建議保持預設。 pool.setAliveCheck(false); // 設定連線失敗恢復開關 // 設定為true,當宕機的伺服器啟動或中斷的網路連線後,這個socket連線還可繼續使用,否則將不再使用. // 預設狀態是true,建議保持預設。 pool.setFailback(true); // 設定容錯開關 // true:噹噹前socket不可用時,程式會自動查詢可用連線並返回,否則返回NULL // 預設狀態是true,建議保持預設。 pool.setFailover(true); // 設定hash演算法 // alg=0 使用String.hashCode()獲得hash code,該方法依賴JDK,可能和其他客戶端不相容,建議不使用 // alg=1 使用original 相容hash演算法,相容其他客戶端 // alg=2 使用CRC32相容hash演算法,相容其他客戶端,效能優於original演算法 // alg=3 使用MD5 hash演算法 // 採用前三種hash演算法的時候,查詢cache伺服器使用餘數方法。採用最後一種hash演算法查詢cache服務時使用consistent方法。 // 預設值為0 pool.setHashingAlg(0); // 設定是否使用Nagle演算法,因為我們的通訊資料量通常都比較大(相對TCP控制資料)而且要求響應及時, // 因此該值需要設定為false(預設是true) pool.setNagle(false); // 設定socket的讀取等待超時值 pool.setSocketTO(3000); // 設定socket的連線等待超時值 pool.setSocketConnectTO(0); // 初始化連線池 pool.initialize(); // 壓縮設定,超過指定大小(單位為K)的資料都會被壓縮 // mcc.setCompressEnable(true); //UnsupportedOperation // mcc.setCompressThreshold(64 * 1024); } private MemCached() { } /** * 獲取唯一例項. * singleton * @return */ public static MemCached getInstance() { return memCached; } /** * 新增一個指定的鍵值對到快取中. * * @param key * @param value * @return */ public boolean add(String key, Object value) { return mcc.add(key, value); } /** * 新增一個指定的鍵值對到快取中. * * @param key * @param value * @param expiry 多久之後過期 * @return */ public boolean add(String key, Object value, Date expiry) { return mcc.add(key, value, expiry); } public boolean set(String key, Object value) { return mcc.set(key, value); } public boolean set(String key, Object value, Date expiry) { return mcc.set(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); }
寫個Main方法測試下:
public static void main(String[] args) { MemCached cache = MemCached.getInstance(); boolean result1 = cache.add("hello", 1234, new Date(1000 * 2));// 設定2秒後過期 System.out.println("第一次add : " + result1); System.out.println("Value : " + cache.get("hello")); boolean result2 =cache.add("hello", 12345, new Date(1000 * 2));// add fail System.out.println("第二次add : " + result2); boolean result3 =cache.set("hello", 12345, new Date(1000 * 2));// set successes System.out.println("呼叫set : " + result3); System.out.println("Value : " + cache.get("hello")); try { Thread.sleep(1000 * 2); System.out.println("已經sleep2秒了...."); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Value : " + cache.get("hello")); }
執行結果如下:
第一次add : true
Value : 1234
第二次add : false
呼叫set : true
Value : 12345
已經sleep2秒了....
Value : null
說明:
- 第二次add失敗是因為"hello"這個key已經存在了。
- 呼叫set成功,是因為set的時候覆蓋了已存在的鍵值對,這正是add和set的不同之處
- 設定過期之間之後,cache按時自動失效
上面的例子是對於基本資料型別,對於普通的POJO而言,如果要進行儲存的話,那麼比如讓其實現java.io.Serializable介面。
因為memcached是一個分散式的快取伺服器,多臺伺服器間進行資料共享需要將物件序列化的,所以必須實現該介面,否則會報錯的(java.io.NotSerializableException)。
下面來試試POJO的儲存:
package memcached.test;
public class Person implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Main方法如下:
public static void main(String[] args) {
MemCached cache = MemCached.getInstance();
Person p1 = new Person();
p1.setName("Jack");
cache.add("bean", p1);
Person p2 = (Person) cache.get("bean");
System.out.println("name=" + p2.getName());//Jack
p2.setName("Rose");
// cache.replace("bean", p2);
Person p3 = (Person) cache.get("bean");
System.out.println("name=" + p3.getName());
}
上面的程式碼中,我們通過p2.setName("Rose")修改了物件的名字,
最後一行列印的會是什麼呢?
name=Jack
name=Jack
Why?
這是因為我們修改的物件並不是快取中的物件,而是通過序列化過來的一個例項物件
那麼要修改怎麼辦?使用replace,註釋掉的那一行把註釋去掉就可以了。
二、其他
Memcached的命令引數說明
-p <num> 監聽的埠
-l <ip_addr> 連線的IP地址, 預設是本機
-d start 啟動memcached服務
-d restart 重起memcached服務
-d stop|shutdown 關閉正在執行的memcached服務
-d install 安裝memcached服務
-d uninstall 解除安裝memcached服務
-u <username> 以<username>的身份執行 (僅在以root執行的時候有效)
-m <num> 最大記憶體使用,單位MB。預設64MB
-M 記憶體耗盡時返回錯誤,而不是刪除項
-c <num> 最大同時連線數,預設是1024
-f <factor> 塊大小增長因子,預設是1.25
-n <bytes> 最小分配空間,key+value+flags預設是48
-h 顯示幫助
Memcached也可以在控制檯中新增鍵值對,首先使用命令“telnet 127.0.0.1 11211”進入到Memcached控制檯,
然後使用set、
add、
replace、
get、
delete來操作。
三、Memcached的優勢和不足
說到Memcached的優勢,那當然是:速度快,操作簡便,易擴充套件
不足的話,主要有2點:
- 資料的臨時性(資料僅儲存在記憶體中)
- 只能通過指定鍵來讀取資料,不支援模糊查詢
四、Memcached停止時的保障措施
如果資料庫的訪問量比較大,就需要提前做好準備,以便應對在memcached停止時發生的負載問題。
如果能在停止memcached之前,把資料複製到其他的server就好了。恩,這個可以通過repcached來實現。
repcached是日本人開發的實現memcached複製功能,
它是一個單master、單slave的方案,但它的master/slave都是可讀寫的,而且可以相互同步
如果master壞掉,slave偵測到連線斷了,它會自動listen而成為master