1. Memcached 사용자 가이드
    1. 개요
    2. 소개
      1. 아키텍처
    3. 설치하기
    4. 실행하기
    5. 설정하기
    6. 사용하기
    7. 결론
  2. 예제코드
  3. 결과

Memcached 사용자 가이드

개요

http://memcached.org/
memcached 는 database, API, 페이지 렌더링 등의 호출 결과를 저장하는 인메모리 키벨류 스토어이다.
무료&오픈소스, 고성능, 분산 메모리 객체 캐쉬 시스템, database 로드를 줄여 동적웹서버의 성능을 늘려준다.
memcached 는 단순하면서도 강력하다. 개발하기 쉽고 대용량 캐쉬가 직면한 문제를 해결하면서 다양한 언어로 API를 제공하고 있다.

소개

2003년 5월 danga interactive의 개발자 Brad Fitzpatrick가 하루에 2천만 PV가 발생하는 LiveJournal.com 사이트의 속도 향상을 위해 개발되었다.
livejournal 이후에 Facebook 에서 큰 규모로 사용하고 있으며
일본의 mixi, 하테나, Vox, LiveJournal, 위키피디어등의 서비스에서 웹어플리케이션의 확장을 향상하는 중요한 수단으로 사용하고 있다.
database, API, 페이지 렌더링 등의 호출이 자주 발생하는 서비스에서 성능을 높이고자 할 때 유용한 해결책이 될 수 있다.

아키텍처

client-server 구조
단순한 구조
libevent 이용하여 이벤트 핸들링을 함
단순한 프로토콜를 이용하고 있어서 API 개발이 용이하다.

일시적인 값을 대상으로 한다.
ram에 보관하고 있다가 부족해지면 가장 오래된 값부터 삭제한다.
max(key) < 250bytes
max(values) < 1Mb
다른 cache 서비스에 비해 다양한 데이터 타입을 제공하지 않는다.
replication 를 지원하지 않는다.
persistence 를 지원하지 않는다.
(재시작하거나 신규 서버추가 시, 캐쉬를 채우기 위해 퍼포먼스 저하 문제가 발생할 수 있다.)
memcached 서버끼리는 통신하지 않고 각각의 클라이언트가 모든 서버를 알고 있어야 한다.
RDBMS에서 무결성을 보장하기 위해 lock 사용하는데 반해 memcached는 사용하지 않는다.
DBMS와 다른 점은 데이터 무결성을 보장하지 않는다.

옵션널하게 binary protocol에 한해 SASL 인증을 지원은 하지만 보통 trusted network 에서 사용하고 많은 기업에서 그렇게 사용하고 있음.

설치하기

CentOS-6.2-x86_64-minimal

memcached 에서 이벤트 핸들링을 하기 위해 사용하는 libevent를 설치한다.

STUDY:root@test1 ~# yum install wget gcc make -y
STUDY:root@test1 ~# wget http://cloud.github.com/downloads/libevent/libevent/libevent-2.0.20-stable.tar.gz
STUDY:root@test1 ~# tar xvfz libevent-2.0.20-stable.tar.gz
STUDY:root@test1 ~# cd libevent-2.0.20-stable
STUDY:root@test1 ~# ./configure
STUDY:root@test1 ~# make && make install
STUDY:root@test1 ~# ln -s /usr/local/lib/libevent-2.0.so.5 /usr/lib64/libevent-2.0.so.5

memcached 설치한다.

STUDY:root@test1 ~# wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz
STUDY:root@test1 ~# tar -zxvf memcached-1.4.15.tar.gz
STUDY:root@test1 ~# cd memcached-1.4.15
STUDY:root@test1 ~# ./configure
STUDY:root@test1 ~# make && make install

실행하기

memcached는 root로 실행할 수 없기 때문에 새로운 계정을 생선해서 실행한다.

STUDY:root@test1 ~# useradd -m memcached_user
STUDY:root@test1 ~# ./memcached -d -u memcached_user -m 256 127.0.0.1 -p 11211
STUDY:root@test1 ~# iptables -F

memcached가 정상 실행된 것을 확인 할 수 있다.

grep -i 11211
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN
tcp 0 0 :::11211 :::* LISTEN

설정하기

-p <num> TCP port number to listen on (default: 11211)
-U <num> UDP port number to listen on (default: 11211, 0 is off)
-s <file> UNIX socket path to listen on (disables network support)
-a <mask> access mask for UNIX socket, in octal (default: 0700)

사용하기

stats
get
set
delete
flush_all

결론

데이터 변경은 적은데 자주 호출되는 정보에 사용하면 많은 성능효과를 볼 것이고,
데이터 무결성을 보장하지 않기 때문에 주의해서 사용해야할 것이다.

예제코드

CacheTest.java


import java.io.IOException;
import java.net.*;
import java.util.*;

import net.spy.memcached.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import com.google.common.base.Strings;

public class CacheTest {
	static MemcachedClientIF memcachedClient;
	static{
		List<InetSocketAddress> serverList = new ArrayList<InetSocketAddress>();
		InetSocketAddress server1 = new InetSocketAddress("mtest1", 11211);
		serverList.add(server1);
		try {
			memcachedClient = new MemcachedClient(serverList);
		} catch (IOException e) {}
	}
	
	public static void main(String[] args) {
		useCache();
		useDb();
	}
	
	private static void useCache(){
		long startTime = System.currentTimeMillis();
		
		for(String name:getName()){
			getCache(name);
		}
		
		System.out.println("cache -> " + (System.currentTimeMillis() - startTime));
	}
	
	private static void useDb(){
		long startTime = System.currentTimeMillis();
		
		for(String name:getName()){
			getEngWord(name);
		}
		
		System.out.println("db -> " + (System.currentTimeMillis() - startTime));
	}

	private static void setCache(String key, String value) {
		memcachedClient.set(key, 600, value);
	}

	public static String getCache(String key) {
		String result = (String) memcachedClient.get(key);
		if(Strings.isNullOrEmpty(result)){
			String newValue = getEngWord(key);
			setCache(key, newValue);
			return newValue;
		}
		return result;
	}
	
	static String getEngWord(String korWord){
		try {
			String req=URLEncoder.encode(korWord, "UTF-8");
			String DIC_URL = "http://endic.naver.com/search.nhn?searchOption=entry_idiom&query="+req;
			Document doc = Jsoup.connect(DIC_URL).get();
			return doc.select("span.fnt_k05").first().text();
		} catch (IOException e) {
			return "";
		}
	}
	
	static List<String> getName(){
		List<String> nameList = new LinkedList<String>();
		nameList.add("한국");
		nameList.add("중국");
		nameList.add("일본");
		nameList.add("미국");
		nameList.add("영국");
		nameList.add("프랑스");
		nameList.add("인도");
		nameList.add("터키");
		nameList.add("스위스");
		return nameList;
	}
	
}

결과

cache -> 31
db -> 1649

#출처
http://cto.vmware.com/author/richardmcdougall/