Memcached 병렬 제어 CAS 프로 토 콜

6550 단어
부분 자료 참조:http://langyu.iteye.com/blog/680052
Memcached 는 1.2.4 버 전에 서 CAS (Check and Set) 프로 토 콜 을 추가 하여 자바 가 병발 하 는 CAS (Compare and Swap) 원자 작업 과 유사 하 게 같은 item 이 여러 스 레 드 로 변경 되 는 과정의 병발 문 제 를 처리 합 니 다.
Memcached 에서 각 key 는 64 - bit 길이 의 long 형 유일한 수 치 를 연결 하여 이 key 가 value 에 대응 하 는 버 전 번 호 를 표시 합 니 다.이 수 치 는 Memcached server 에서 생 성 되 며 1 부터 같은 Memcached server 는 중복 되 지 않 습 니 다.두 가지 상황 에서 이 버 전의 수 치 는 1: 1 을 추가 하고 key - value 쌍 을 추가 합 니 다.2. 키 에 대응 하 는 value 값 을 업데이트 하 는 데 성 공 했 습 니 다.아 이 템 버 전 값 을 삭제 하면 줄 어 들 지 않 습 니 다.
예 를 들 면:
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" 를 얻 습 니 다. 이 값 을 사용 하지만 다른 스 레 드 에 의 해 수정 되 었 는 지 모 르 면 문제 가 발생 할 수 있 습 니 다.
CAS 협 의 는 이런 병발 수정 문 제 를 해결 했다.현재 key - value 에 대한 value 를 수정 하려 는 스 레 드 가 있 을 때 gets 방법 으로 item 의 버 전 번 호 를 받 습 니 다. 작업 이 완료 되 었 을 때 카 스 방법 으로 신중하게 변경 합 니 다. 로 컬 에서 item 작업 과정 에서 이 key - value 가 Memcached server 에서 다른 스 레 드 로 변경 되 었 다 면 이번 수정 (낙관적 잠 금 개념) 을 포기 합 니 다.
CASValue casValue = client.gets(key);
//*****
//       
//*****
CASResponse response = client.cas(key, newValue, casValue);
//      item     casValue.getCas(),        item           。      ,           ,  Memcached server          ,  true false            (              ,       )

병발 환경 에서 의 정확성 검증
테스트 장면: Memcached client (C +, 자바 클 라 이언 트 모두 가능) 2 개 를 사용 하여 같은 key 값 을 동시에 변경 합 니 다. 하 나 는 value 를 1 로 추가 하고 하 나 는 value 를 1 로 줄 입 니 다. 만약 에 한 작업 이 실패 하면 (이번 읽 기 에서 변경 하 는 과정 에서 다른 프로 세 스 가 값 을 수 정 했 기 때 문) 수 치 를 수정 하 는 작업 이 실 패 했 습 니 다. 1 또는 1 을 추가 하여 한 변수 에 잠시 저장 합 니 다.다음 에 성공 할 때 한꺼번에 더 하거나 빼 면 데이터 의 정확성 을 확보 할 수 있다.아래 에 제 가 선택 한 두 개의 클 라 이언 트 프로그램 은 각각 C + + 와 자바 프로그램 입 니 다. 물론 두 개 모두 C + 와 자바 프로그램 도 마찬가지 입 니 다.
(memcached get () 방법 으로 데이터 포인 터 를 얻 은 후 메모리 방출 을 기억 하 십시오. 그렇지 않 으 면 메모리 유출 이 발생 할 수 있 습 니 다.http://docs.libmemcached.org/memcached_get.html)
//============================================================================
// Name        : memcached_cpp.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C, Ansi-style
//============================================================================

#include <libmemcached/memcached.h>
#include <vector>
#include <sys/msg.h>
#include <errno.h>
#include <string>
#include <iostream>
#include <sys/file.h>
#include <stdio.h>
#include <vector>
#include <sys/time.h>
#include<time.h>
#include <math.h>
#include<sstream>

using namespace std;

int q2alen=0;
int alertfd=0;


string numberToString(int d){
	std::stringstream ss;
	ss<<d;
	string str = ss.str();
	return str;
}


/*
 * @author: roger
 * @version: 2014-05-17 17:45:10
 *
 *libmemcached        ,  ,  ,    
 */
int main() {

	memcached_st *memc;
	memcached_return rc;
	memcached_server_st *server;
	time_t expiration = 0 ;   //   0      
	uint32_t flags =32 ;  //   java     ,       32

	memc = memcached_create(NULL);
	server = memcached_server_list_append(NULL, "localhost", 11211, &rc);
	rc = memcached_server_push(memc, server);  //set,get         
	memcached_server_list_free(server);
	string value = "2";
	size_t value_length = value.length();   //get       value   ,  0
	size_t key_length ;

	rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);

	int num=1;

	string key = "dai";

	int i =0;
	while(i<10000){

		char * val = memcached_get(memc, key.c_str(), key.length(), &value_length,&flags, &rc);
//		cout<<memc->result.item_cas<<endl;

		int a = atoi(val);
		a = a-num;
		string val2 = numberToString(a);

		rc = memcached_cas(memc, key.c_str(), key.length(), val2.c_str(),val2.length(), expiration, flags,memc->result.item_cas);
		if (rc != MEMCACHED_SUCCESS) {
			num++; //      ,    2 ,    
		}
		else{
			num = 1;//   ,     1
		}

		i++;
	}



//	free,    ,    ,    memcached   
	memcached_free(memc);
	return 0;
}
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
import com.schooner.MemCached.MemcachedItem;

public class test2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MemCachedClient client=new MemCachedClient();
        String [] addr ={"localhost:11211"};    //ip、   
        Integer [] weights = {3};
        
        //SockIOPool Memcached              
        SockIOPool pool = SockIOPool.getInstance();  
        pool.setServers(addr);
        pool.setWeights(weights);  
        pool.setInitConn(5);  
        pool.setMinConn(5);  
        pool.setMaxConn(200);  
        pool.setMaxIdle(1000*60*60);  
        pool.setMaintSleep(30);  
        pool.setNagle(false);  
        pool.setSocketTO(30);  
        pool.setSocketConnectTO(0);  
        pool.initialize();
        
//        client.set("dai", "0");  //      
        
//        int result = (Integer) client.get("dai");   	//    
//        System.out.println(result);
        
        
        int num = 1;  //     1
        
        int a =0;
        while (a<10000) {
        	MemcachedItem item = client.gets("dai");
            String value = (String) item.getValue();
            long cas = item.getCasUnique();
            int value2 = Integer.valueOf(value)+num;
            
            boolean issuccess =client.cas("dai", String.valueOf(value2), cas);
            if (!issuccess) {
    			num++;  //      ,    2 ,    
    		}
            else {
				num = 1;  //     ,       1
			}
            
            a++;
		}
        
	}

}

두 프로그램 이 동시에 실 행 됩 니 다. 중간 에 겹 치 는 부분 은 동시에 value 를 수정 하 는 부분 이자 우리 가 테스트 하 는 곳 입 니 다. 실행 이 끝 난 후에 memcached 의 값 이 0 인 것 을 발견 하면 병행 제어 에 성공 한 것 을 나타 냅 니 다.

좋은 웹페이지 즐겨찾기