TokyoCabinet/TokyoTyrant を Rails で使う
インストール
TokyoCabinet
% wget http://tokyocabinet.sourceforge.net/tokyocabinet-1.3.27.tar.gz % tar zxvf tokyocabinet-1.3.27.tar.gz % cd tokyocabinet-1.3.27 % ./configure --prefix=/usr/local % make % make check % sudo make install
TokyoCabinet Ruby API
% wget http://tokyocabinet.sourceforge.net/rubypkg/tokyocabinet-ruby-1.18.tar.gz % tar zxvf tokyocabinet-ruby-1.18.tar.gz % cd tokyocabinet-ruby-1.18 % ruby extconf.rb % make % sudo make install
TokyoTyrant
% wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.11.tar.gz % tar zxvf tokyotyrant-1.1.11.tar.gz % cd tokyotyrant-1.1.11 % ./configure --prefix=/usr/local % make % sudo make install
TokyoTyrant Ruby API
% wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-ruby-1.2.tar.gz % tar zxvf tokyotyrant-ruby-1.2.tar.gz % cd tokyotyrant-ruby-1.2 % sudo ruby install.rb
動作確認
TokyoCabinetの確認
% ruby example.rb hop foo:hop bar:step baz:jump quux:touchdown touchdown foo:hop bar:step baz:jump quux:touchdown
TokyoTyrantの確認
% sudo ttservctl start % ruby example-tyrant.rb hop foo:hop bar:step baz:jump touchdown foo:hop bar:step baz:jump quux:touchdown
ひとまず動くことを確認.
設定
特に設定ファイルは無くて,ttservctl(/usr/local/sbin/ttservctl)に直書きされている.
8 # configuration variables 9 prog="ttservctl" 10 cmd="ttserver" 11 basedir="/var/ttserver" 12 port="1978" 13 pidfile="$basedir/pid" 14 logfile="$basedir/log" 15 ulogdir="$basedir/ulog" 16 ulimsiz="256m" 17 sid=1 18 dbname="$basedir/casket.tch#bnum=1000000" 19 maxcon="65536" 20 retval=0
サーバの実行自体は次のような感じ.
39 $cmd \ 40 -port "$port" \ 41 -dmn \ 42 -pid "$pidfile" \ 43 -log "$logfile" \ 44 -ulog "$ulogdir" \ 45 -ulim "$ulimsiz" \ 46 -sid "$sid" \ 47 "$dbname"
ということで,これを見習って手動でやってみる.
% ttserver -port 1978 -dmn -pid "$PWD/ttserver.pid" -log "$PWD/ttserver.log" -ulog "$PWD/ttserver.ulog" -ulim "256m" -sid "1" "$PWD/casket.tch#bnum=1000000" % ruby example-tyrant.rb hop foo:hop bar:step baz:jump touchdown foo:hop bar:step baz:jump quux:touchdown
ここで pid/log/ulog/dbname に関しては full-path でなければ動作しないので注意が必要.
Ruby のオブジェクトを保存するには
Marshal.dump/Marshal.load を使います.
ここではちゃんと取り出せているかどうかを調べてるんですが,同一オブジェクトかどうかを判断するために == を再定義しています.
Rails で使う
試しに以下のようなサンプルを作って動かしてみます.
% rails tt-test % cd tt-test % ruby script/generate model User name:string % ruby script/generate model --skip-migration UserAccessLog
ユーザ(User)とそのアクセス日時記録(UserAccessLog)です.TyokyoTyrant は memcached 互換なんですが,それはおいといて,単なるデータベースとして扱ってみます.
% ruby script/console >> u = User.new({:name => "hogehoge"}) => #<User id: 1, name: "hogehoge", created_at: "2009-01-09 04:11:26", updated_at: "2009-01-09 04:11:26"> >> u.access_time => nil >> u.access_time = Time.now => Fri Jan 09 13:31:25 0900 2009 >> u.access_time => Fri Jan 09 13:31:25 0900 2009 >> exit % ruby script/console >> u = User.find(1) => #<User id: 1, name: "hogehoge", created_at: "2009-01-09 04:11:26", updated_at: "2009-01-09 04:11:26"> >> u.access_time => Fri Jan 09 13:31:25 0900 2009
これで透過的に TokyoTyrant を扱うことができました.mixiのように,アクセス時間の記録などには,非常に強力なデータベースとして扱うことができるので,使い方次第では負荷分散できそうです.