天天看點

xmemcached釋出1.0-BETA版

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

繼續閱讀