Memcached 설치 및 사용 방법 (2012-09-13)


목차

개요

  • memcached 는 이름 그대로 메모리를 사용해 캐시서비스를 제공해주는 데몬이다. memcache 라는 이름의 라이브러리가 많은데, 여기서 설명하는 건 '데몬'이다.
  • memcached 는 LiveJournal을 개발한 Brad Fitzpatrick 이 개발했다. 유투브나 아마존, 위키피디아, 소스포지, 트위터 등 많은 대형 사이트에서 사용되고 있는 데몬이다.
  • memcached 운용시 시스템의 메모리 상황를 모니터링 해, 스왑과 락이 일어나지 않도록 해야한다. memcached는 스왑이 일어나지 않을 정도로 메모리는 여유있다는 가정하에 개발되었다고 한다. 메모리가 부족해 스왑이 일어나 메모리에 저장했던 컨텐츠가 스왑 디스크에 저장되면, 심각한 속도 저하가 있을 것이다.
  • memcached 는 메모리에 데이터를 캐시하는 데몬이며, 아래와 같은 사용은 지양해야 한다.
    • 파일의 캐시로 사용하지 말 것. 단순한 파일 캐시는 OS상에서 제공해준다. memcached는 파일을 읽고 가공한 것을 캐시해야 한다.
    • 데이터베이스 쿼리 결과의 캐시로 사용하지 말 것. 위와 비슷한 이유다. 요즘 나오는 대부분의 상용 DBMS는 쿼리결과를 캐시해주기 때문에 이중으로 캐시할 필요 없다.
  • memcached - a distributed memory object caching system

설치

  • libevent

    memcached 설치에는 libevent 라이브러리가 필요하다. 이 라이브러리는 이벤트(예를 들어 시그널이나 타입아웃)가 발생했을 때 콜백 함수를 쉽게 호출할 수 있도록 도와주는 라이브러리다.
    libevent
    root@wl ~/src # wget --no-check-certificate https://github.com/downloads/libevent/libevent/libevent-2.0.20-stable.tar.gz
    root@wl ~/src # tar xvfz libevent-2.0.20-stable.tar.gz
    root@wl ~/src # cd libevent-2.0.20-stable
    root@wl ~/src/libevent-2.0.20-stable # ./configure CFLAGS="-I/usr/local/ssl/include" CPPFLAGS="-I/usr/local/ssl/include"
    root@wl ~/src/libevent-2.0.20-stable # make
    root@wl ~/src/libevent-2.0.20-stable # make install
    
  • memcached

    root@wl ~/src # wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz
    root@wl ~/src # tar xvfz memcached-1.4.15.tar.gz
    root@wl ~/src # cd memcached-1.4.15
    root@wl ~/src/memcached-1.4.15 # ./configure --enable-dtrace
    root@wl ~/src/memcached-1.4.15 # make
    root@wl ~/src/memcached-1.4.15 # make install
    
  • libMemcached

    • memcached 는 TCP로 데몬에 접속해 메시지를 주고 받는 방법으로 사용한다. 따라서 라이브러리를 제공하지 않고 memcached 프로토콜 스펙만 제공해준다. 이를 래핑해 사용하기 쉽도록 만든 라이브러리가 libmemcached 이다.
    • libMemcached 는 현재 Solaris Studio 12.3 으로 컴파일 되지 않는다. (#pragma once 미지원) 솔라리스에 번들된 GCC컴파일러로도 안된다. 필자의 경우 GCC 4.6.2 를 사용했다. GCC 4.6.2를 설치하려면 윈디하나의 솔라나라: GCC (작성중)를 참고하자. 이 문서의 내용을 진행함에 있어 libMemcached 라이브러리는 컴파일하지 않아도 된다.
    • libMemcached
    root@wl ~/src # wget --no-check-certificate https://launchpad.net/libmemcached/1.0/1.0.10/+download/libmemcached-1.0.10.tar.gz
    root@wl ~/src # tar xvfz libmemcached-1.0.10.tar.gz
    root@wl ~/src # cd libmemcached-1.0.10
    root@wl ~/src/libmemcached-1.0.10 # ./configure --with-memcached --disable-64bit --enable-umem
    ...
    ---
    Configuration summary for libmemcached version 1.0.5
    
       * Installation prefix:       /usr/local
       * System type:               pc-solaris2.10
       * Host CPU:                  i386
       * C Compiler:                gcc (GCC) 4.6.2
       * Assertions enabled:        yes
       * Debug enabled:             no
       * Warnings as failure:       no
    
    ---
    root@wl ~/src/libmemcached-1.0.5 # /usr/sfw/bin/gmake
    root@wl ~/src/libmemcached-1.0.5 # /usr/sfw/bin/gmake install
    

실행

  • memcached 설정 및 실행

    • 데몬을 띄울 포트번호와 사용할 최대 메모리 양을 정한다. 기본 포트는 11211 번이며, 사용할 최대 메모리는 64MB이 기본 값이다.
    • memcached 는 별도의 설정 파일을 제공하지 않는다.
    root@wl ~ # memcached -h 1)
    memcached 1.4.15
    ...
    -l <addr>     바인드할 주소
    -p <num>      TCP 포트 번호 (기본값: 11211)
    -U <num>      UDP 포트 번호 (기본값: 11211, 0 인경우 사용안함)
    -s <file>     UNIX 소켓 경로 (네트워크 지원 안함)
    -d            데몬으로 실행
    -u <username> 전환할 사용자 이름(루트로 실행시)
    -m <num>      최대 메모리(MB단위, 기본값: 64)
    -M            데이터 저장시 메모리가 부족할 경우 오류를 반환(기본값은 오래된 데이터를 삭제)
    -c <num>      최대 접속 개수 (기본값: 1024)
    -P <file>     PID 파일 저장 위치. -d 옵션 사용시 사용
    -f <factor>   증가 팩터값. (기본값: 1.25)
    -n <bytes>    키+값+플래그를 저장할 최소 단위(기본값: 48)
    -L            large memory pages 사용(가능한경우)
    -t <num>      사용할 쓰레드 개수 (기본값: 4)
    -v            로그 보임
    -vv           자세한 로그 보임
    -vvv          매우 자세한 로그 보임
    ...
    
    1) 도움말. 중요하다고 생각되는건 번역했다. 대형 사이트의 경우 도움말을 참조해 메모리관련 옵션 최적화를 반드시 수행해야 한다.

    아래 커맨드는 windy 사용자의 권한을 사용하고, 64MB 메모리를 사용하고, 큰 페이지를 사용하며, 127.0.0.1만 바인드(외부 접속 불가)하는 데몬을 띄운다. PID 파일은 /tmp/memcached.pid 에 있다.
    root@wl ~ # memcached -u windy -d -m 64 -l 127.0.0.1 -p 11211 -L -P /tmp/memcached.pid
    
    memcached 는 kill 을 사용해 종료하면 된다.
    root@wl ~ # kill `cat /tmp/memcached.pid`
    
  • memcached 프로토콜 예제

    memcached 의 프로토콜은 두가지다. 바이너리 프로토콜과 아스키 프로토콜이 그것인데, 아스키 프로토콜은 telnet 등을 사용해 아래와 같이 이용할 수 있다. 부하가 많이 걸리는 곳에서는 바이너리 프로토콜이 아스키 프로토콜에 비해 성능이 '약간' 좋은 것으로 알려져있다.
    root@wl ~ # telnet localhost 11211 
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    stats settings 1)
    STAT maxbytes 67108864
    STAT maxconns 1024
    STAT tcpport 11211
    STAT udpport 11211
    STAT inter NULL
    STAT verbosity 0
    STAT oldest 0
    STAT evictions on
    STAT domain_socket NULL
    STAT umask 700
    STAT growth_factor 1.25
    STAT chunk_size 48
    STAT num_threads 4
    STAT num_threads_per_udp 4
    STAT stat_key_prefix :
    STAT detail_enabled no
    STAT reqs_per_event 20
    STAT cas_enabled yes
    STAT tcp_backlog 1024
    STAT binding_protocol auto-negotiate
    STAT auth_enabled_sasl no
    STAT item_size_max 1048576
    STAT maxconns_fast no
    STAT hashpower_init 0
    END
    set mykey 0 100 2
    hi 2)
    STORED
    get mykey 3)
    VALUE mykey 0 2
    hi
    END
    Ctrl+]
    telnet> Ctrl+D
    Connection to localhost closed.
    root@wl ~ # 
    
    1) 세팅 확인
    2) 데이터 저장
    3) 데이터 추출
  • 기본 튜닝

    TCP 스펙상 접속을 끊은 후 TIME_WAIT 대기 시간이 발생한다. 30~240초로 설정할 수 있는데, 대부분의 운영체제에서는 240초가 기본값이다. 하지만 이 값은 memcached 를 운용하는 환경에서는 너무 길다. 트래픽이 많은 곳에서 memcached 와 빈번하게 통신하다 보면, TIME_WAIT가 수만개 이상 발생하는 경우가 있고, 이로인해 memcached 에 접속이 안되는 현상이 발생하는 경우가 있기 때문이다. (어느 정도까지 문제 없는지는 운영체제마다, 설정마다 다르다) 따라서 각 운영체제 마다 이를 줄여주는 옵션이 있다. memcached 를 실행한 서버에서 아래와 같이 30초로 세팅한다. 참고로 TCP표준은 최소 60초 이상을 권장한다.
    • 솔라리스
      root@wl ~ # ndd -set /dev/tcp tcp_time_wait_interval 30000
      root@wl ~ # export EVENT_NOEVPORT=1
      
    • 리눅스
      root@wll ~ # vi /etc/sysctl.conf 
      net.ipv4.ip_local_port_range = 16384 65534
      net.ipv4.tcp_fin_timeout = 30
      net.ipv4.tcp_tw_reuse = 1
      root@wll ~ # sysctl -p
      
    • 윈도
      C:\>edit tcptimewait.reg
      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
      "TcpTimedWaitDelay"=dword:0000001e
      C:\>regedit /S tcptimewait.reg
      
  • memcached 와 DTrace

    현재 지원되는 프로바이더와 프로브는 아래와 같다. (아래 예제를 따라하기 전에 먼저 memcached 데몬을 실행해야 한다)
    root@wl ~ # dtrace -l -m memcached
       ID   PROVIDER            MODULE                          FUNCTION NAME
     2752 memcached16537         memcached                      assoc_delete assoc-delete
     2753 memcached16537         memcached                        assoc_find assoc-find
     2754 memcached16537         memcached                      assoc_insert assoc-insert
     2755 memcached16537         memcached               complete_update_bin command-add
     2756 memcached16537         memcached              complete_nread_ascii command-add
     2757 memcached16537         memcached               complete_update_bin command-append
     2758 memcached16537         memcached              complete_nread_ascii command-append
     2759 memcached16537         memcached              complete_nread_ascii command-cas
     2760 memcached16537         memcached                      do_add_delta command-decr
     2761 memcached16537         memcached            process_delete_command command-delete
     2762 memcached16537         memcached                process_bin_delete command-delete
     2763 memcached16537         memcached               process_get_command command-get
     2764 memcached16537         memcached                   process_bin_get command-get
     2765 memcached16537         memcached                      do_add_delta command-incr
     2766 memcached16537         memcached               complete_update_bin command-prepend
     2767 memcached16537         memcached              complete_nread_ascii command-prepend
     2768 memcached16537         memcached               complete_update_bin command-replace
     2769 memcached16537         memcached              complete_nread_ascii command-replace
     2770 memcached16537         memcached               complete_update_bin command-set
     2771 memcached16537         memcached              complete_nread_ascii command-set
     2772 memcached16537         memcached                 process_bin_touch command-touch
     2773 memcached16537         memcached                          conn_new conn-allocate
     2774 memcached16537         memcached                          conn_new conn-create
     2775 memcached16537         memcached                         conn_free conn-destroy
     2776 memcached16537         memcached                 dispatch_conn_new conn-dispatch
     2777 memcached16537         memcached                        conn_close conn-release
     2778 memcached16537         memcached                      do_item_link item-link
     2779 memcached16537         memcached                    do_item_remove item-remove
     2780 memcached16537         memcached                   do_item_replace item-replace
     2781 memcached16537         memcached             do_item_unlink_nolock item-unlink
     2782 memcached16537         memcached                    do_item_unlink item-unlink
     2783 memcached16537         memcached                    do_item_update item-update
     2784 memcached16537         memcached                    conn_set_state process-command-end
     2785 memcached16537         memcached                   process_command process-command-start
     2786 memcached16537         memcached              dispatch_bin_command process-command-start
     2787 memcached16537         memcached                    do_slabs_alloc slabs-allocate
     2788 memcached16537         memcached                    do_slabs_alloc slabs-allocate-failed
     2789 memcached16537         memcached                     do_slabs_free slabs-free
     2790 memcached16537         memcached                  do_slabs_newslab slabs-slabclass-allocate
     2791 memcached16537         memcached                  do_slabs_newslab slabs-slabclass-allocate-failed
    
    아래와 같이 memcached_watch.d 스크립트를 작성해 DTrace 를 실행하고 위의 프로토콜 예제를 다시 따라하면 [command-set fired]가 출력될 것이다. Ctrl+C를 눌러 종료한다.
    root@wl ~ # cat memcached_watch.d
    /* TO RUN: dtrace -s memcached_watch.d -p `pgrep -x memcached` -q */
    dtrace:::BEGIN
    {
            printf("Hit Ctrl-C to end.\n");
    }
    memcached*:::command-set
    {
            printf("command-set fired\n");
    }
    root@wl ~ # dtrace -s memcached_watch.d -p `pgrep -x memcached` -q
    Hit Ctrl-C to end.
    command-set fired
    ^C
    

JAVA/JSP

  • JAVA에서 memcached 를 사용하기 위한 라이브러리 중 spymemcached에 대해 소개한다.
  • 설치는 단순히 http://spymemcached.googlecode.com/files/spymemcached-2.8.4.jar 를 받아 CLASS PATH에 복사해놓으면 된다.
  • 홈페이지: spymemcached
memcache.java
 다운로드 (717 바이트)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package test;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
 
import net.spy.memcached.MemcachedClient;
 
/**
 * Memcached Sample.
 * WindyHana's Solanara - Memcached http://www.solanara.net/solanara/memcached
 * java test.MemcachedSample
 */
public class MemcachedSample {
    /**
     * 테스트 함수
     * @param args
     */
    @SuppressWarnings("unused")
    public static void main(String[] args) {
        MemcachedClient c;
        try {
            c = new MemcachedClient(new InetSocketAddress("localhost", 11211));
            c.set("someKey", 3600, new HashMap<String, Object>());
            Object myObjeckt = c.get("someKey");
            c.delete("someKey2");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

PHP

PHP에서 memcached 를 사용하기 위한 모듈은 두가지를 제공한다. PECL:memcachePECL:memcached 가 그것인데, 두가지 모두 memcached 에 접속해 사용한다. 단지 PECL:memcache는 memcached 에 직접 접속하는 PHP 모듈이고, PECL:memcached 는 libMemcached 를 통해 memcached 에 접속하는 모듈이라는 점이 다르다. PHP에서의 사용 방법이나 지원 함수도 조금씩 다르므로 매뉴얼을 확인하자.
  • PECL:memcache 를 설치하기 위해서는 autoconf 가 필요하다. 윈디하나의 솔라나라: Autotools - autoconf를 참고해 autoconf 를 설치하자.
  • PECL:memcache 설치 및 설정

    root@wl ~/src # mkdir phpmemcache
    root@wl ~/src # cd phpmemcache
    root@wl ~/src/phpmemcache # /usr/local/php/bin/pecl download memcache
    root@wl ~/src/phpmemcache # tar xvf memcache-2.2.7.tgz
    root@wl ~/src/phpmemcache # cd memcache-2.2.7
    root@wl ~/src/phpmemcache/memcache-2.2.7 # /usr/local/php/bin/phpize
    root@wl ~/src/phpmemcache/memcache-2.2.7 # CFLAGS="-xc99" ./configure -with-php-config=/usr/local/php/bin/php-config
    root@wl ~/src/phpmemcache/memcache-2.2.7 # make
    root@wl ~/src/phpmemcache/memcache-2.2.7 # cp memcache.php /usr/local/php/lib/php
    root@wl ~/src/phpmemcache/memcache-2.2.7 # cp ./modules/memcache.so /usr/local/php/lib/php/extensions
    
    php.ini 를 수정해야 한다. 윈디하나의 솔라나라: SAMP의 [PHP 설정]를 참조해 extension_dir 을 설정하고 아래와 같이 extension 을 추가해야 한다.
    root@wl ~ # vi /usr/local/php/lib/php.ini
    extension=memcache.so
    
  • memcached 세션 설정

    PHP의 세션 핸들러로 memcached 를 설정할 수 있으며, 저장 경로로 두개 이상의 memcached 데몬을 사용할 수 있다. php 세션을 위한 memcached 의 키값은 [memc.sess.key] 형식으로 정해진다.
    root@wl ~ # vi /usr/local/php/lib/php.ini
    session.save_handler = memcache
    session.save_path = "127.0.0.1:11211"
    
  • PHP - memcache 테스트

    memcache.phps
     다운로드 (534 바이트)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php session_start(); ?>
    <pre>
    <?php
    $presessdata = @$_SESSION["data"];
    $_SESSION["data"] = @$_SESSION["data"] + 1;
     
    $memcache = new Memcache;
    $memcache->connect("localhost", 11211);
    print_r($memcache->getStats());
     
    $items = array(
        'key1' => 'value1',
        'key2' => 'value2',
        'key3' => 'value3'
    );
    foreach ($items as $k => $v) {
        $memcache->set($k, $v);
    }
    var_dump($memcache->get(array('key1', 'key3')));
    var_dump($memcache->get('key2'));
    var_dump($memcache->get('key4'));
    ?>
    SESSION: <?php echo $_SESSION["data"]; ?>
    </pre>
    아래와 유사하게 출력되어야 한다.
    Array
    (
        [pid] => 16700
        [uptime] => 425530
        [time] => 1333412724
        [version] => 1.4.15
        [libevent] => 2.0.20-stable
        [pointer_size] => 32
        [rusage_user] => 6.387770
        [rusage_system] => 4.913250
        [curr_connections] => 5
        [total_connections] => 57
        [connection_structures] => 7
        [reserved_fds] => 20
        [cmd_get] => 148
        [cmd_set] => 45
        [cmd_flush] => 0
        [cmd_touch] => 0
        [get_hits] => 100
        [get_misses] => 48
        [delete_misses] => 6
        [delete_hits] => 0
        [incr_misses] => 0
        [incr_hits] => 0
        [decr_misses] => 0
        [decr_hits] => 0
        [cas_misses] => 0
        [cas_hits] => 0
        [cas_badval] => 0
        [touch_hits] => 0
        [touch_misses] => 0
        [auth_cmds] => 0
        [auth_errors] => 0
        [bytes_read] => 66307
        [bytes_written] => 36315
        [limit_maxbytes] => 67108864
        [accepting_conns] => 1
        [listen_disabled_num] => 0
        [threads] => 4
        [conn_yields] => 0
        [hash_power_level] => 16
        [hash_bytes] => 262144
        [hash_is_expanding] => 0
        [expired_unfetched] => 0
        [evicted_unfetched] => 0
        [bytes] => 27437
        [curr_items] => 20
        [total_items] => 45
        [evictions] => 0
        [reclaimed] => 0
    )
    array(2) {
      ["key1"]=>
      string(6) "value1"
      ["key3"]=>
      string(6) "value3"
    }
    string(6) "value2"
    bool(false)
    SESSION: 1
  • igbinary

    • php serializer중 하나다. PHP의 표준 serializer 보다 메모리를 덜 소비하고, 성능도 더 좋다. libmemcached 와 PECL:memcached 를 설치해야 memcached 와 함께 사용할 수 있다.
    • PECL: igbinary
    root@wl ~/src # /usr/local/php/bin/pecl download igbinary
    root@wl ~/src # tar xvfz igbinary-1.1.1.tgz
    root@wl ~/src # cd igbinary-1.1.1
    root@wl ~/src/igbinary-1.1.1 # /usr/local/php/bin/phpize
    root@wl ~/src/igbinary-1.1.1 # CFLAGS="-xc99" ./configure --with-php-config=/usr/local/php/bin/php-config
    root@wl ~/src/igbinary-1.1.1 # make
    root@wl ~/src/igbinary-1.1.1 # cp ./modules/igbinary.so /usr/local/php/lib/php/extensions
    root@wl ~/src/igbinary-1.1.1 # vi /usr/local/php/lib/php.ini
    extension=igbinary.so
    session.serialize_handler=igbinary
    ;apc.serializer=igbinary


출처 - http://www.solanara.net/solanara/memcached




'Computer Science > Cache' 카테고리의 다른 글

EHCache  (0) 2013.02.11
Hazelcast 소개  (0) 2012.11.06
Memcached의 확장성 개선  (0) 2012.11.06
memcached를 적용하여 사이트 성능 향상  (0) 2012.11.06
Memcached 구현 소개  (0) 2012.11.06
Posted by linuxism
,