Repcacheを調べてみる

Repcacheを調べるに至るまでの経緯

Railsにおけるデータの高速化及び可用性を高めたい!
ということで、ネットを彷徨っていたら memcachedという素晴らしいツールがあるということが分かった。


高速化については、memcachedでキャッシュサーバを構築し、セッションやDBのデータをそこで保管する方法がある。
しかし、memcached単体では単なるキャッシュサーバとしてしか機能せず、データの保全という意味では冗長化は望めない。
もともと冗長化のコンセプトはなさそうなので、仕方のないところ。


Webアプリ側で、冗長化を図ることは可能だが、アプリ側が意識しないところでデータが冗長化されているのが望ましい。
そして、なによりRails(Ruby)に、memcached冗長化させるオプションがない。
なお、PHPには"redundancy"というオプションがあるらしい。


ネットを彷徨っていると、memcachedレプリケーション機能を実装しているrepcacheに出会った。
これを利用しない手はない。


http://lab.klab.org/wiki/Repcached
素晴らしいツールをありがとうございますm(_ _)m

環境

OSと使用パッケージなど

OS Fedora14(x86_64)*1
memcached 1.2.8
repcache 2.2

レプリケーションの構成

node1:* node2:11212
node1:11212 node2:*
準備作業
  • 既存のmemcachedを無効にする(memcachedがインストールされている場合のみ)
chkconfig memcached off
service memcached stop
service iptables stop
chkconfig iptables off
chkconfig ip6tables off 
vi /etc/sysconfig/selinux
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=disabled
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
SELINUXTYPE=targeted
  • とりあえずupdate
yum update -y
  • 必要なパッケージをインストール

memcached-tool を使いたいので memcached もインストール

yum install -y memcached wget libevent-devel make gcc gcc-c++
  • なんとなく再起動
reboot
Repcacheのインストール
wget http://downloads.sourceforge.net/repcached/memcached-1.2.8-repcached-2.2.tar.gz
tar zxf memcached-1.2.8-repcached-2.2.tar.gz
cd memcached-1.2.8-repcached-2.2
./configure --enable-replication --prefix=/opt/memcached-1.2.8-repcached-2.2
make
make install
  • 起動テスト
    • node1側
cd /opt/memcached-1.2.8-repcached-2.2/bin
./memcached -v -x node2 -u root
    • node2側
cd /opt/memcached-1.2.8-repcached-2.2/bin
./memcached -v -x node1 -u root
    • Rails側でセッションをmemcachedに保管するように設定

config/initializers/session_store.rb

ActionController::Base.session = {
  :memcache_server => ["node1:11211", "node2:11211"],
  :expire_after => 10,
  :namespace => "app-#{ENV['RAILS_ENV']}",
  :key         => '_app_session',
  :secret      => '789db92e8a6162f2185368ab0a1e5d8f2761bb25ebfb88e0b3e7ae4fe803d42981d32d96ca544aeb178e840f00f477c83bd370ff7d11f3de3f232052b59c83ce'
}

ActionController::Base.session_store = :mem_cache_store
    • Railsのアプリを適当に動かす
    • node1側のキャッシュを確認
memcached-tool node1 dump
    • node2側のキャッシュを確認
memcached-tool node2 dump
    • 両nodeに同じ情報が書き込まれていたら成功

Dumping memcache contents
Number of buckets: 1
Number of items : 1
Dumping bucket 6 - 1 total items
add app-development:35863ec3d930ce3d21239e4de3e31293 0 1294514243 211

Repcache用のサービス作成
vi /etc/init.d/repcache
#! /bin/sh
#
# chkconfig: - 55 45
# description:  The memcached daemon is a network memory cache service.
# processname: memcached
# config: /etc/sysconfig/memcached
# pidfile: /var/run/memcached/memcached.pid

# Standard LSB functions
#. /lib/lsb/init-functions

# Source function library.
. /etc/init.d/functions

EXEC=/opt/memcached-1.2.8-repcached-2.2/bin/memcached
REPHOST=localhost

PORT=11211
USER=memcached
MAXCONN=1024
CACHESIZE=64
OPTIONS=""

if [ -f /etc/sysconfig/memcached ];then
        . /etc/sysconfig/memcached
fi

# Check that networking is up.
. /etc/sysconfig/network

if [ "$NETWORKING" = "no" ]
then
        exit 0
fi

RETVAL=0
prog="repcache(memcached)"
pidfile=${PIDFILE-/var/run/memcached/memcached.pid}
lockfile=${LOCKFILE-/var/lock/subsys/memcached}

start () {
        echo -n $"Starting $prog: "
        # Ensure that /var/run/memcached has proper permissions
        if [ "`stat -c %U /var/run/memcached`" != "$USER" ]; then
                chown $USER /var/run/memcached
        fi

        daemon --pidfile ${pidfile} $EXEC -d -x $REPHOST -p $PORT -u $USER  -m $CACHESIZE -c $MAXCONN -P ${pidfile} $OPTIONS
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop () {
        echo -n $"Stopping $prog: "
        killproc -p ${pidfile} $EXEC
        RETVAL=$?
        echo
        if [ $RETVAL -eq 0 ] ; then
                rm -f ${lockfile} ${pidfile}
        fi
}

restart () {
        stop
        start
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status -p ${pidfile} $prog
        RETVAL=$?
        ;;
  restart|reload|force-reload)
        restart
        ;;
  condrestart|try-restart)
        [ -f ${lockfile} ] && restart || :
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|try-restart}"
        RETVAL=2
        ;;
esac

exit $RETVAL

※/etc/init.d/memcachedをコピーして作った。

chmod +x /etc/init.d/repcache
chkconfig --add repcache
chkconfig repcache on
chkconfig --list | grep repcache
vi /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

REPHOST=node1
  • サービスとして起動&停止
service repcache start
service repcache stop

調べた結果

OS的に同一スペックのマシン同士であれば、何の支障もなくレプリケーションできる。
しかし少しでもスペックが異なるとレプリケーション出来なかった。

  • 試した例と結果
node1 node2 結果 内容
CentOS 5.5 32bit Fedora14 64bit NG node1からnode2にコピーした場合、node2が残りっぱなしになる。node2からnode1にコピーできない。
Fedora14 64bit(ノーマル) Fedora14 64bit(Oracleインストール版)*2 NG node1からnode2にコピーした場合、node2が残りっぱなしになる。node2からnode1にコピーできない。
Fedora14 64bit(ノーマル) Fedora14 64bit(ノーマル) OK 正常に動いた。


レプリケーションを有効にした場合、マルチスレッドが無効になるところが辛いが、Webアプリの高速化と可用性を向上する方法は確認できた。
とりあえず、Repcacheを導入する方向で進めよう。

*1:本当は使い慣れたCentOSの64bit版にインストールしたかったが、memcachedが提供されていなかったので、Fedoraの64bit版にした。

*2:セマフォや共有メモリの設定がノーマル側と異なる。という意味です。