關於Memcached CAS協議

來源:互聯網
上載者:User

個人小結:簡單來說,CAS(Check and Set)是一個確保並發一致性的機制,屬於“樂觀鎖”範疇;原理很簡單:拿版本號碼,操作,對比版本號碼,如果一致就操作,不一致就放棄任何操作,操作後版本號碼加1。

聯想另外一個機制,與這個有點類似:防重複提交

1.makeToken:server產生一個token,並傳到頁面中,也就是版本號碼(只要不重新整理頁面,這個值都不變);

2.checkValid:提交時對比頁面傳來的token和server中的token,如果相同則提交,不同則放棄;

3.makeToken:更新server中的token。

Struts1與Struts2的原理類似,只不過前者需要開發人員手動調用相應函數,後者可以使用攔截器更簡潔的完成。

----------參考文章------------------

引用:http://langyu.iteye.com/blog/680052

什麼是CAS協議 

Memcached於1.2.4版本新增CAS(Check and Set)協議類同於Java並發的CAS(Compare and Swap)原子操作,處理同一item被多個線程更改過程的並發問題。 

在Memcached中,每個key關聯有一個64-bit長度的long型惟一數值,表示該key對應value的版本號碼。這個數值由Memcached server產生,從1開始,且同一Memcached server不會重複。在兩種情況下這個版本數值會加1:1、新增一個key-value對;2、對某已有key對應的value值更新成功。刪除item版本值不會減小。 

例如 

Java代碼  

MemcachedClient client = new MemcachedClient();  

   client.set("fKey", "fValue");   

  //第一次set, 在Memcached server中會維護fKey對應的value的版本號碼,假設是548;  

  

   client.set("fKey", "sValue");   

  //再次set,則這個fKey對應的value的版本號碼變為549;  

  

   CASValue casValue = client.gets("fKey");  

  //這樣就可以得到對應key的cas版本號碼和實際value(各個Memcached client都有類似的對象表示,名字可能不一樣,但效果類同),如 casValue.getValue = "sValue",casValue.getCas=549;  

CAS協議解決的問題 

類比多個Memcached client並發set同一個key的情境。如clientA想把當前key的value set為"x",且操作成功;clientB卻把當前key的value值由"x"覆蓋set為"y",這時clientA再根據key去取value時得到"y"而不是期望的"x",它使用這個值,但不知道這個值已經被其它線程修改過,就可能會出現問題。 

CAS協議解決這種並發修改問題。有線程試圖修改當前key-value對的value時,先由gets方法得到item的版本號碼,操作完成提交資料時,使用cas方法謹慎變更,如果在本地對item操作過程中這個key-value對在Memcached server端被其它線程更改過,就放棄此次修改(樂觀鎖概念)。 

Java代碼  

CASValue casValue = client.gets(key);  

//*****  

//本地的各種處理  

//*****  

CASResponse response = client.cas(key, newValue, casValue);  

//在我取資料時item的版本號碼是casValue.getCas(),所以提交時我期望item的版本號碼是沒有改變過的。如果被修改過,不是我取資料時的版本號碼,那麼Memcached server對這次提交什麼也不做,返回true或false由使用者自己來提出解決方案(什麼也不做或是重新擷取版本號碼,再次重試提交等)  

並發環境下的正確性驗證 

用多個Memcached client並發更改同一個key值,將value遞增,如果  操作次數-CAS失敗次數 = value增加的值,表示並發環境下CAS處理沒有問題。 

Java代碼  

import java.io.IOException;  

import java.net.InetSocketAddress;  

  

import net.spy.memcached.CASResponse;  

import net.spy.memcached.CASValue;  

import net.spy.memcached.MemcachedClient;  

  

  

public class CASTest {  

      

    private static MemcachedClient client = null;  

      

    static {  

        try {  

            client = new MemcachedClient(  

                                new InetSocketAddress("localhost", 11211));  

        } catch (IOException o) {  

            o.printStackTrace();  

        }  

    }  

  

    public static void main(String[] args) throws Exception {  

        //Firstly, the key should exist.  

        //key is "number", value is Integer 1, 7845 is expire time  

        client.set("number", 7845, 1);  

          

          

        CASTest testObj = new CASTest();  

        //start the multithread environment  

        for (int i = 0; i < 10; i++) {  

            testObj.new ThreadTest("Thread-" + (i + 1)).start();  

        }  

    }  

      

    /** 

     * Each thread runs many times 

     */  

    private class ThreadTest extends Thread {  

          

        private  MemcachedClient client = null;  

        ThreadTest(String name) throws IOException {  

            super(name);  

            client = new MemcachedClient(  

                                  new InetSocketAddress("localhost", 11211));  

        }  

          

        public void run() {  

            int i = 0;  

            int success = 0;  

            while (i < 10) {  

                i++;  

                CASValue<Object> uniqueValue =client.gets("number");  

                CASResponse response = client.cas("number",     

                 uniqueValue.getCas(), (Integer)uniqueValue.getValue() + 1);  

  

                if (response.toString().equals("OK")) {  

                    success++;  

                }  

                System.out.println(Thread.currentThread().getName() + " " +  i   

                  + " time " + " update oldValue : " + uniqueValue   

                  +  " , result : " + response);  

            }  

              

            if (success < 10) {  

                System.out.println(Thread.currentThread().getName()  

                      + " unsuccessful times : " + (10 - success ));  

            }  

        }  

    }  

}  

每次執行的結果都會不一樣,如其中某次的執行結果為: 總共操作100次,衝突47次,且最後value由1漲到53,那麼表示驗證成功。 

不足之處,誠請提出!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.