2013年1月22日火曜日

memcachedのインストール&設定

■memcachedとは?
memcachedを知り尽くすから抜粋 http://gihyo.jp/dev/feature/01/memcached/0001
memcachedは,LiveJournalを運営していたDanga Interactive社で,Brad Fitzpatrick氏が中心となって開発されたソフトウェアです。

現在ではmixiやはてな,Facebook,Vox,LiveJournalなど,さまざまなサービスでWebアプリケーションのスケーラビリティを向上させる重要な要素になっています。

多くのWebアプリケーションは,RDBMSにデータを格納し,アプリケーションサーバでそのデータを引き出してブラウザ等に表示させています。
しかしデータが大量になったり,アクセスが集中すると,RDBMSの負荷があがり,データベースのレスポンスが悪化し,Webサイトの表示が遅延するなど大きな影響がでてしまいます。

そこでmemcachedが活躍します。memcachedは高性能な分散メモリキャッシュサーバです。
通常,データベースへの問い合わせ結果を一時的にキャッシュすることで,
データベースへのアクセス回数を減らし,動的なウェブアプリケーションの高速化やスケーラビリティの向上のために利用されています。

弊社のシステムでは、セッション情報や、更新頻度が少ないデータ、
API結果などをmemcachedで保存させ利用しています。

以前は、memcachedを利用せずに、各サーバーで直接静的なファイルとして出力し、
その結果をそのまま利用するという形を使っていた頃もありましたが、
負荷分散のためサーバーが増えていくと管理が大変という点と、
静的ファイルよりインメモリのmemcachedの方が高速らしいです(゚д゚)!

静的ファイルを生成すると、ファイルシステムのバッファリング遅延とIO負荷が増えてしまう。
ネットワークコストが大きい場合や、ディスクI/Oに対してメモリが不足しているとか以外ではmemcachedのが(・∀・)イイ!!

memcachedをセッション機能として利用するだけでも結構便利です!
ド━━━━m9(゚∀゚)━━━━ン!!

■メリット
・高速。
・RDBMSの負荷を軽減できる。
・静的ファイルの管理がなくなる分楽チン

■デメリット
・キャッシュが消失する可能性がある。(永続性が無くOSやmemcachedが再起動された場合には全て消える。また、有効期限やキャッシュサイズの上限値を超えた場合には自動で古いから消えたりする。)
・RDBMSみたいに複雑な条件を利用した検索などが行えない。
・トランザクション処理が無かったり、データをどのタイミングで更新するのかなどはアプリケーション側でやる必要があり、データの最新状態、不整合の管理は大変。

※デメリットの消失する可能性がある問題は、永続KVSであるTokyoTyrantとKyotoTycoonなどで解決可能。(Memcached互換あり)
※ファイルキャッシュとmemcachedの比較はこちらの方がされています。

それではインストール&設定を行って行きたいと思います!
■手順1)インストールする。 memcachedをインストールするにはlibeventが必要な為、インストールする
#libeventのインストール
yum install libevent
  Installing : libevent-1.4.13-4.el6.x86_64                                                                                                                                                  1/1
  Verifying  : libevent-1.4.13-4.el6.x86_64                                                                                                                                                  1/1

Installed:
  libevent.x86_64 0:1.4.13-4.el6

Complete!
libevent-develのインストール
yum install libevent-devel
Installed:
  libevent-devel.x86_64 0:1.4.13-4.el6

Dependency Installed:
  libevent-doc.noarch 0:1.4.13-4.el6                                                            libevent-headers.noarch 0:1.4.13-4.el6

Complete!
memcachedのインストール
yum --enablerepo=remi install memcached

memcached-1.4.15-2.el6.remi.x86_64.rpm                                                                                                                                    |  79 kB     00:01
警告: rpmts_HdrFromFdno: ヘッダ V3 DSA/SHA1 Signature, key ID 00f97f56: NOKEY
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi
Importing GPG key 0x00F97F56:
 Userid : Remi Collet <RPMS@FamilleCollet.com>
 Package: remi-release-6-1.el6.remi.noarch (installed)
 From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-remi
Is this ok [y/N]: y
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : memcached-1.4.15-2.el6.remi.x86_64                                                                                                                                            1/1
  Verifying  : memcached-1.4.15-2.el6.remi.x86_64                                                                                                                                            1/1

Installed:
  memcached.x86_64 0:1.4.15-2.el6.remi

Complete!
※memcachedのバグがあるそうなので、memcachedのバージョンは、1.4.7以降のものをなるべく利用すること。ヽ(゚∀。)ノ
詳しく知りたい方はこちらを読んでみてください
mixi大規模障害について - mixi Engineers' Blog

■手順2)設定の変更
設定ファイルの/etc/sysconfig/memcachedを編集します
vi /etc/sysconfig/memcached
#ポート番号(デフォルト11211)
PORT="11211"
#実行ユーザー
USER="memcached"
#最大同時接続数(デフォルト1024)
MAXCONN="1024"
#利用するメモリサイズ(単位はMB)32bitでは3GBまでしか有効にならない。
CACHESIZE="64"
#オプション
OPTIONS="-d -vv 1>> /var/log/memcached.log 2>> /var/log/memcached.log"
各オプションの説明は次のようになっています。
-d
デーモンとしてバックグラウンドで起動
-vv
デバッグモード
他にも次のようなオプションがあるみたいです。
# memcached -h
memcached 1.4.15
-p       TCP port number to listen on (default: 11211)
-U       UDP port number to listen on (default: 11211, 0 is off)
-s      UNIX socket path to listen on (disables network support)
-a      access mask for UNIX socket, in octal (default: 0700)
-l      interface to listen on (default: INADDR_ANY, all addresses)
               may be specified as host:port. If you don't specify
              a port number, the value you specified with -p or -U is
              used. You may specify multiple addresses separated by comma
              or by using -l multiple times
-d            run as a daemon
-r            maximize core file limit
-u  assume identity of  (only when run as root)
-m       max memory to use for items in megabytes (default: 64 MB)
-M            return error on memory exhausted (rather than removing items)
-c       max simultaneous connections (default: 1024)
-k            lock down all paged memory.  Note that there is a
              limit on how much memory you may lock.  Trying to
              allocate more than that would fail, so be sure you
              set the limit correctly for the user you started
              the daemon with (not for -u  user;
              under sh this is done with 'ulimit -S -l NUM_KB').
-v            verbose (print errors/warnings while in event loop)
-vv           very verbose (also print client commands/reponses)
-vvv          extremely verbose (also print internal state transitions)
-h            print this help and exit
-i            print memcached and libevent license
-P      save PID in , only used with -d option
-f    chunk size growth factor (default: 1.25)
-n     minimum space allocated for key+value+flags (default: 48)
-L            Try to use large memory pages (if available). Increasing
              the memory page size could reduce the number of TLB misses
              and improve the performance. In order to get large pages
              from the OS, memcached will allocate the total item-cache
              in one large chunk.
-D      Use  as the delimiter between key prefixes and IDs.
              This is used for per-prefix stats reporting. The default is
              ":" (colon). If this option is specified, stats collection
              is turned on automatically; if not, then it may be turned on
              by sending the "stats detail on" command to the server.
-t       number of threads to use (default: 4)
-R            Maximum number of requests per event, limits the number of
              requests process for a given connection to prevent
              starvation (default: 20)
-C            Disable use of CAS
-b            Set the backlog queue limit (default: 1024)
-B            Binding protocol - one of ascii, binary, or auto (default)
-I            Override the size of each slab page. Adjusts max item size
              (default: 1mb, min: 1k, max: 128m)
-S            Turn on Sasl authentication
-o            Comma separated list of extended or experimental options
              - (EXPERIMENTAL) maxconns_fast: immediately close new
                connections if over maxconns limit
              - hashpower: An integer multiplier for how large the hash
                table should be. Can be grown at runtime if not big enough.
                Set this based on "STAT hash_power_level" before a
                restart.

オプション 内容 Default値
-p  ListenするTCPポート番号 11211
-U  ListenするUDPポート番号 0, off
-s  UnixソケットへのPath(ネットワークは非サポート) 
-a  Unixソケットのアクセスマスク 0700
-l  memcachedがListenするIPアドレス INDRR_ANY
-d デーモンとして起動する場合は指定 
-r コアファイルの上限を最大にする 
-u  memcachedを起動するユーザ名(root権限で実行した場合のみ有効) 
-m  最大メモリ使用量(単位:MB) 64
-M メモリを使い果たしたときにエラーを返す(勝手にキャッシュを削除しない) 
-c  最大同時接続数 1024
-k  
-v verboseモードで起動して、errorとwarningを出力 
-vv very verboseモードで起動してデバックメッセージやエラーをコンソールへ出力 
-h memcachedのバージョンとヘルプを表示 
-i memcachedとlibeventのライセンスを表示 
-b 管理インスタンスの起動 
-p  PIDファイルの保存ファイル(デーモンとして起動した場合のみ有効) 
-f  チャンクサイズの増加係数 1.25
-n  キャッシュ1件(key+value+flags)に割り当てる最小サイズ(単位:byte) 48
■手順3)起動&自動起動登録
#起動
# /etc/init.d/memcached start
memcached を起動中:                                        [  OK  ]
# ps axu|grep memcached
497      25009  0.0  0.0 339964  1184 ?        Ssl  14:01   0:00 memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid -d -m 64 -p 11211 -c 1024
root     25017  0.0  0.0 107456   924 pts/2    D+   14:01   0:00 grep memcached

#自動起動の設定
# chkconfig memcached on
■手順4)接続を行う
#telnet接続
# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
#statsを入力する
stats
STAT pid 25009
STAT uptime 438
STAT time 1358831313
STAT version 1.4.15
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 0.007998
STAT rusage_system 0.005999
STAT curr_connections 10
STAT total_connections 12
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 29
STAT bytes_written 593
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evictions 0
STAT reclaimed 0
END
#telnetを終了させるにはquitを入力する
quit
Connection closed by foreign host.
※statsを「stats settings」にすると、起動時の設定が表示される。

■手順5)外部サーバーからの接続を行う
#ポートが開放されていることの確認
# netstat -nlp | grep memcached
tcp        0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      25009/memcached
tcp        0      0 :::11211                    :::*                        LISTEN      25009/memcached
udp        0      0 0.0.0.0:11211               0.0.0.0:*                               25009/memcached
udp        0      0 :::11211                    :::*                                    25009/memcached

#外部サーバー接続してみる。
# telnet memcachedサーバーのIPアドレス 11211
Trying ***.***.***.**...
Connected to ***.***.***.**.
Escape character is '^]'.
stats
STAT pid 25009
STAT uptime 15077
STAT time 1358845952
STAT version 1.4.15
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 0.307953
STAT rusage_system 0.140978
STAT curr_connections 10
STAT total_connections 16
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 60
STAT bytes_written 1621
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evictions 0
STAT reclaimed 0
END
quit
Connection closed by foreign host.
■手順6)外部サーバーからの接続に制限を行う。
memcachedはIPアドレス制限に1つのIPしか指定できないため、
iptablesを利用して接続制限を行います。

iptablesの設定を行う場合には、既存でサーバーに設定されているポート番号の開放などにも気をつけてください:(;゙゚'ω゚'):
今回の設定ではSSHのポート番号にはデフォルトの22番を利用していますので、
任意で変更してある場合には、その番号に適切な値に変更して利用してください。
そうしないと、SSHで接続できなくなりますガ━━(;゚Д゚)━━ン!!

サーバー上で利用されているポート番号などはnetstat -nlpなどで確認が行えますので、
そこに表示されるLISTENされているポート番号は開放してあげてください。

また、iptablesでは開放しているが、ポート番号がLISTENされていないポート番号には接続はできませんので、
両方の確認を忘れずに!!m9っ`Д´) ビシッ!!
#現在の設定を確認(未設定の状態。ポート番号の制限無しの状態)
/sbin/iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
設定を一旦リセットしたい場合(/etc/sysconfig/iptablesの中身は消えない)
iptables -F
iptablesを編集する
vi /etc/sysconfig/iptables
#テーブルをfilterの指定。パケットフィルタリング
*filter

#入力(受信)パケットのチェイン
:INPUT   ACCEPT [0:0]
#転送パケットのチェイン
:FORWARD ACCEPT [0:0]
#出力(送信)パケットのチェイン
:OUTPUT  ACCEPT [0:0]

#セッション確立後のパケット疎通は許可
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

#プロトコルのicmpを許可
-A INPUT -p icmp -j ACCEPT

#ローカル(自分自身)からの入力許可
-A INPUT -i lo -j ACCEPT

#プロトコルがtcpで、ポート番号が22の接続開始パケット(新規接続)を許可
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

#プロトコルがtcpで、ポート番号が11211、送信元の接続開始パケット(新規接続)を許可
-A INPUT -p tcp -m state --state NEW -m tcp --dport 11211 -s memcachedの接続を許可するサーバーIPアドレス -j ACCEPT

#ここまでの条件に一致しなかったパケットは、ICMPパケット"host-prohibited"を返して接続拒否
-A INPUT -j REJECT --reject-with icmp-host-prohibited
##ここまでの条件に一致しなかったパケットは、ICMPパケット"host-prohibited"を返して接続拒否
-A FORWARD -j REJECT --reject-with icmp-host-prohibited

#
COMMIT
■手順7)iptablesの再起動
#再起動
/etc/rc.d/init.d/iptables restart
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: チェインをポリシー ACCEPT へ設定中nat filter mang[  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]

#設定の確認
# /sbin/iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh
ACCEPT     tcp  --  memcachedの接続を許可するサーバーIPアドレス       anywhere            state NEW tcp dpt:memcache
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
■手順8)外部サーバーからの接続を試す。
#iptablesでmemcachedの接続が許可されていないサーバーからmemcachedの接続を試す。
$ telnet memcachedサーバーのIPアドレス 11211
Trying ***.***.***.**...
telnet: connect to address ***.***.***.**: No route to host

#iptablesで指定されているサーバーへ移動し、memcachedの接続を試す。
$ telnet memcachedサーバーのIPアドレス 11211
Trying ***.***.***.**...
Connected to ***.***.***.**.
Escape character is '^]'.
quit
Connection closed by foreign host.

以上(`・ω・´)ゞビシッ!!

■ログローテート(未解決)
-vvオプションを利用してログファイルを出している時に、
ログファイルのローテートを行いたいのですが、
それが正しく動作しない・・・・ガ━━(;゚Д゚)━━ン!!

ローテートは正しくされるが、ファイルの出力先がローテートしたファイルのままになってしまい、
新規で作成されたファイル出力されない現象になっていました(´;ω;`)ブワッ

lsofで開いているファイルを見てみると、やはりログローテートされたファイルを見てしまっているようでした( ´゚д゚`)エー
memcached 28814 memcached    1w      REG             145,61     2887   20889612 /var/log/memcached/11212.log-20130123
memcached 28814 memcached    2w      REG             145,61     2887   20889612 /var/log/memcached/11212.log-20130123
こちらの方と同じ現象かな・・・? ログローテートの設定は次のようにしてあります・・・orz
view /etc/logrotate.d/memcached
#ファイル名にlogが付くファイルを対象にする
/var/log/memcached/*.log {
 #create 640 mysql mysql
 #ログファイルが空ならローテーションしない
 notifempty
 #ログを毎日ローテーションする
 daily
 #ローテーションする回数を指定
 rotate 10
 #ログファイルが存在しなくてもエラーを出さずに処理を続行
 missingok
 #末尾を日付にする
 dateext
 #末尾を日付にする際のフォーマット(Ymdしか使えない?)
 dateformat -%Y%m%d
 #ファイル作成
 create 0777 root root
 #一度のみ実行
 sharedscripts
 #postrotateとendscriptの間に記述されたコマンドをログローテーション後に実行
 postrotate
  /bin/kill -HUP `cat /var/run/memcached.pid 2> /dev/null` 2> /dev/null || true
 endscript
}
神の降臨を待ちしております(゚∀゚)神のヨカーン

参考URL

2 件のコメント:

  1. create 0777 root root

    copytrancate
    にすれば動くと思われる

    返信削除
    返信
    1. ご指摘ありがとうございます!

      copytrancateを知らなかったので調べてみたらなんとなくいけそうですね!
      時間が出来たら検証してみたいと思います!(ΦωΦ)フフフ…

      ありがとうございました~!(`・ω・´)ゞビシッ!!

      削除