1、支援更多協定,在已有協定支援的基礎上添加了append、prepend、gets、批量gets、cas協定的支援,具體請檢視xmemcachedclient類的執行個體方法。重點是cas操作,下文将較長的描述下。
2、memcached分布支援,支援連接配接多個memcached server,支援簡單的餘數分布和一緻性哈希分布。
3、0.60版本以來的bug修複。
memcached 1.2.4之後開始支援cas協定,該協定存儲資料同時發送一個版本号,隻有當這個版本号與memcached server上該key的最新版本一緻時才更新成功,否則傳回exists,版本号的擷取需要通過gets協定獲得,cas全稱就是compare and set,如果對hibernate樂觀鎖和java.util.concurrent.atomic包都比較熟悉的話這個概念應該很了解了。xmemcached 1.0-beta開始支援cas協定,看例子:
xmemcachedclient client = new xmemcachedclient();
client.addserver("localhost",11211);
client.set("a", 0, 1); //設定a為1
getsresponse result = client.gets("a");
long cas = result.getcas(); //擷取目前cas
//嘗試更新a成2
if (!client.cas("a", 0, 2, cas))
system.err.println("cas error");
xmemcachedclient.cas(final string key, final int exp, object value, long cas)将嘗試更新key的值到value,如果失敗就傳回false。這樣搞好像很麻煩,需要先gets擷取cas值,然後再調用cas方法更新,是以xmemcached提供了一個包裝類可以幫你搞定這兩步,并且提供重試機制:
/**
* 合并gets和cas,利用casoperation
*/
client.cas("a", 0, new casoperation() {
@override
public int getmaxtries() {
return 10;
}
public object getnewvalue(long currentcas, object currentvalue) {
system.out.println("current value " + currentvalue);
return 2;
});
通過casoperation,你隻要實作兩個方法即可,getmaxtries傳回最大重試次數,超過這個次數還沒有更新成功就抛出timeoutexception;getnewvalue方法傳回依據目前cas和緩存值,你希望設定的更新值。看一個cas更詳細的例子,開100個線程遞增緩沖中的變量a,采用cas才能保證最後a會等于100:
import java.util.concurrent.countdownlatch;
import net.rubyeye.xmemcached.casoperation;
import net.rubyeye.xmemcached.xmemcachedclient;
/**
* 測試cas
* @author dennis
*/
class casthread extends thread {
private xmemcachedclient mc;
private countdownlatch cd;
public casthread(xmemcachedclient mc, countdownlatch cdl) {
super();
this.mc = mc;
this.cd = cdl;
}
public void run() {
try {
if (mc.cas("a", 0, new casoperation() {
return 50;
system.out.println("currentvalue=" + currentvalue
+ ",currentcas=" + currentcas);
return ((integer) currentvalue).intvalue() + 1;
}))
this.cd.countdown();
} catch (exception e) {
e.printstacktrace();
}
}
public class castest {
static int num = 100;
public static void main(string[] args) throws exception {
xmemcachedclient mc = new xmemcachedclient();
mc.addserver("192.168.222.100", 11211);
// 設定初始值為0
mc.set("a", 0, 0);
countdownlatch cdl = new countdownlatch(num);
// 開num個線程遞增變量a
for (int i = 0; i < num; i++)
new casthread(mc, cdl).start();
cdl.await();
// 列印結果,最後結果應該為num
system.out.println("result=" + mc.get("a"));
mc.shutdown();
最高重試次數設定成了50,觀察輸出你就會知道cas沖突在高并發下非常頻繁,這個操作應當慎用。
說完cas,我們再來看下xmemcached對分布的支援。
1、如何添加多個memcached server?
通過xmemcachdclient.addserver(string ip,int port)方法,
xmemcachedclient mc = new xmemcachedclient();
mc.addserver(ip1, port1);
mc.addserver(ip2, port2);
mc.addserver(ip3, port3);
mc.addserver(ip4, port3);
2、怎麼分布?
在xmemcached啟動consistent hashing如下:
xmemcachedclient client = new xmemcachedclient(new ketamamemcachedsessionlocator(hashalgorithm.crc32_hash));
client.addserver(ip, 12000);
client.addserver(ip, 12001);
client.addserver(ip, 11211);
client.addserver(ip, 12003);
client.addserver(ip, 12004);
散列函數采用crc32,你也可以采用其他散列函數,具體看場景測試而定,散列函數決定了你的查找節點效率和緩存重新分布的均衡程度。
文章轉自莊周夢蝶 ,原文釋出時間 2009-03-09