System Compleat.

Memcached 의 사용.

Techs

정윤진 ( yjjeong@rsupport.co.kr )


시스템을 하면서 느끼는 부분은, 개발에서 어떤 시스템 자원을 필요로 하는지 모르면 최상의 퍼포먼스를 구현하기 어렵다는 점이다. 뭐 해보신 분들에게는 당연한 이야기겠지만, 다르게 말하면 어플리케이션 ( 웹이던 웹이 아니던 ) 에서 사용하는 라이브러리나 함수를 모르고는 극한의 튜닝은 힘들고, 이 마저도 제대로 건드리지 못하면 사용자 몇백명에도 버벅대는 시스템이 나올 수 있다.   또는 문제가 발생한 경우, 실제 개발자가 나는 잘못 없어 라고 두손 두발 들어버리면 각종 장애에 대한 부담은 시스템 하는 사람이 떠안기 때문에, 괜히 문제도 없는 시스템에서 패킷 덤프도 뜨고 메모리 덤프도 떠 가면서 GC는 정상 동작 하는지, 각 프로세스나 스레드의 상태등을 체크하면서 상욕을 하는 경우도 많이 있다.

따라서 개발자 만큼은 아니더라도 적어도 우리가 서비스 하고 있는데 사용되는 핵심적인 라이브러리와, 그 라이브러리가 어떠한 방식으로 시스템 자원을 사용하는지 정도에 대한 이해는 항상 필요하지만 요즘과 같이 윈도우, 유닉스등 멀티 플랫폼으로 구성된 서비스의 경우엔 많이 헤메기 마련이다. 그래서, 사실 쉽지 않은 직업이라고도 생각한다.

유닉스의 경우엔, 최악의 경우 strace 를 사용해 보는 방법 ( 극악 무도한 방법이면서 시간이 걸리긴 하지만 ) 을 통해 추적의 실마리 정도는 잡아 낼 수 있다.  농담처럼 아파치에 strace 거는 소리 하고 있네  라고 떠들기도 하지만, 실제 이렇게 잡아내는건 거의 노가다란 사실.
그나마 Open Solaris 등 최신의 SunOS 들은 dtrace 라는 막강한 툴을 제공하기도 하지만.

뭐 서론이 너무나도 길어져 버렸지만, 오늘 이야기 하고자 하는 Memcached 는 이름에서와 같이 Cache 처리를 하는 어플리케이션이다.  PHP 에도 붙이고, 아파치에도 붙이고, Nginx 및 원하면 Perl 에도 가져다 붙일 수 있는 이 강력한 캐시관련 툴은, 경우에 따라 비약적인 서버성능을 가져다 줄 수 있다.

PHP의 extension 으로 제공되는 eAccelerator 나, xcache 와는 다르다.
( 덧붙이자면, eAccelerator 는 실행 환경에 사용될 수 없기 때문에 최근에는 xcache 를 더 선호하는 편이다. )

모든 Cache 가 그렇지만, 적용을 잘 해야한다.  이 잘 해야 한다는 말의 의미는, 데이터가 자주 변경될 가능성이 있는곳에 가져다 붙이면 쓸데 없이 데이터를 cache 에 넣거나, 넣은 데이터가 맞는 데이터인지 검증해야 하는 오버헤드가 붙게 된다.  하지만,  데이터가 자주 변할 가능성이 낮은 구간에 적용한다면 비약적인 성능의 향상을 가져 올 수 있다.


더군다나 풍부한 클라이언트 API의 지원으로, php, perl, python, ruby, java 뿐 아니라
MySQL, PostgreSQL 에도 적용 가능한 UDF 도 제공하기 때문에 그것이 웹 - DB 의 중간자이든, 웹에서 사용되는 세션이건, 각 서비스에 필요한 어떠한 형태의 무엇이건 간에 그 사용의 단순성으로  어느 서비스에나 쉽게 적용 될 수 있겠다.


memcached 는 기본적으로 객체 ( Object ) 를 저장하는데 사용되지만, string 과 같은 직렬화 될 수 있는 어떤 변수라도 저장 할 수 있다.  memcached 에 데이터를 넣는데는 다음 4개의 인자만 주어지면 된다.

유일 키 - 캐시 내부의 데이터 검색용. 레코드 자체가 고유 아이디인 경우 ( 이를테면 세션 ) 그 자체로 키로서 사용 가능하다.

저장 변수 - 직렬화 되어 저장되고 비 직렬화 되어 검색될 수 있다면 어떤 유형이든 가능하다.

Boolean -  압축 여부  ( 압축에 의한 오버헤드와 메모리 저장공간에 대해 생각한다 )

Cache Expire time -  캐쉬가 종료될 시간을 지정한다. 0으로 지정된 경우 캐시에서 절대 지워지지 않는다.

뭐 예제의 경우, 나보다 더 잘 써 놓은 사람들이 있으니 내가 새로 짤 필요는 없다고 생각한다.
따라서 danga 페이지의 Perl 에 적용한 예를 퍼다 담아 본다.


Perl Example

sub get_foo_object {
   my $foo_id = int(shift);
   my $obj = $::MemCache->get("foo:$foo_id");
   return $obj if $obj;

   $obj = $::db->selectrow_hashref("SELECT .... FROM foo f, bar b ".
                                   "WHERE ... AND f.fooid=$foo_id");
   $::MemCache->set("foo:$foo_id", $obj);
   return $obj;
}


리눅스 및 유닉스 등에서 각종 시스템 관리 에 사용하는 툴에도 물론 사용 가능하겠다.
뭐 조악한 예를 들자면, DB 에 저장된 각 시스템의 리소스들에 대한 접근 정보를 퍼담아서
캐쉬에 넣고 사용 할 수도 있겠지.

아무튼 memcached 에 넣은 데이터에 대한 검색, 생성, 삭제 등 모든 액션이 가능하고,
TCP/IP 를 지원하기 때문에 실 시스템의 위치에 관계 없이 구성 가능 하다.

실제 성능에 대한 분석은, 이것 역시 굳이 직접 하지 않아도 될 일이다.  본인이 일하고 있는
사이트에서 이러한 로직을 적용 가능한 구간을 색출하여 한번 비교 분석해 보면 될 일이다.


시스템 관리자가 할 일은, 코드레벨에서 로직의 검증이 아니다. 성능을 분석하고, 사용 가능한 각종 퍼포먼스 튜닝의 방법을 로직에 어떻게 적용할지에 대한 사용가능한 가장 안정적인 해법과 실제 구현을 위한 개발자와의 대화 능력이다.  실 서비스에 적용하기 전에 베타시스템이 존재한다면 베타에 적용하여 두고, 각 API 에 대한 링크를 개발자에게 주는 것만으로 큰 도움이 될 수 있다.


요새는 뭐 항상 당연한 이야기만 쓰고 있는것 같은데, 암튼 2년전에 사용했던 memcached 는
아주 유용 했기에, 요새 nginx 때문에 다시금 보게 되어 반가운 마음에 한번 정리한다.

설치나 기타 뭐 APM 과 같은 환경에서의 운용은, 다른 분들이 잘 설명해 놓은게 많지만
나는 IBM의 링크를 추천한다. ( 다른 PHP 관련 튜닝도 볼 수 있으니까 )


우리 서비스 ( Rsupport 의 서비스 ) 에 적용 할 수 있는 부분은, 아마도 닷넷용 클라이언트 라이브러리를 사용하여 서비스에 녹이는 방법이 있을 수 있겠다.  닷넷쪽에는 이번에 MS MVP이신 webgenie 님이 ( 장현희 과장님이 ㅋ ) 새로 오셨기 때문에  만약 필요 하다면 언제는 지원이 가능할 것이라 생각 된다.  후훗, 앞으로 만들어질 서비스가 기대 된다.


관련 페이지:
memcached Home page
http://www.danga.com/memcached/

IBM 의 memcached 를 사용한 PHP 성능 향상에 관한 링크
http://www.ibm.com/developerworks/kr/library/os-php-fastapps3/index.html

sf.net 의 memcached client library
http://sourceforge.net/projects/memcacheddotnet/

윈도 서버 사용자라고 울지 마시라!   memcached for win32
http://jehiah.cz/projects/memcached-win32/