Tokyo CabinetとTokyo Tyrantについて、社内勉強会のために作ったスライドをSlideShareに公開しました。(スライドはKeynote形式でダウンロード可能です)その解説と補足をしておきます。勉強会の目的は、Tokyo CabinetとTokyo Tyrantを大づかみに理解することと、実際にデータ操作をしてみることでした。
http://www.slideshare.net/akirakoyasu/tokyo-cabinet-tokyo-tyrant-10468880
まずはTokyo Cabinet/Tokyo Tyrantとは何なのか、端的に言えば、
ということになります。(スライド2-8)
Tokyo Cabinet(以下TC)はいわゆるkey-valueストアで、4種類のデータ構造を持つことができます。(スライド10-17)
TCはデータ操作のためのCLIを備えています。データ構造によっていくらかの違いはありますが、例えばhashDBを操作する場合は以下のようにします。(スライド18-23)
# カレントディレクトリに"casket.tch"というファイル名でhashDBを作成する tchmgr create casket.tch # key"hoge"に紐づくvalue"fuga"を挿入する tchmgr put casket.tch "hoge" "fuga" # key"hoge"に紐づくvalueを参照する tchmgr get casket.tch "hoge" # hashDBのkeyを一覧する tchmgr list casket.tch # key"hoge"を削除する tchmgr out casket.tch "hoge"
これらの他にもいくつかコマンドがありますし、多数のオプションもあります。詳細はmanページを参照してください。
TCの操作はネイティブライブラリとして提供され、また、他のプログラム言語から使用するためのAPIが提供されます。基本的に先ほどのCLI(正確にはネイティブライブラリ)に準ずるメソッド・オプションとなるよう作られています。スライドではJavaAPIの例を挙げています。(スライド25)
Tokyo Tyrant(以下TT)はTCをデータストレージとして使用するDBサーバです。これは実際にサーバを起動してデータ操作をする手順を見ていただきましょう。(スライド28-36)
まずは1つ目のコンソールでTTを起動します。以下コンソール番号をプロンプトで示します。
# TTを起動する。(デフォルトポート1978) # データストレージにはカレントディレクトリの"casket.tch"を作成/使用する。 console1:$ ttserver casket.tch
2つ目のコンソールでデータ操作を行いましょう。
# key"hoge"に紐づくvalue"fuga"を挿入する console2:$ tcrmgr put localhost "hoge" "fuga" # key"hoge2"に紐づくvalue"fuga2"を挿入する console2:$ tcrmgr put localhost "hoge2" "fuga2" # key"hoge"に紐づくvalueを参照する console2:$ tcrmgr get localhost "hoge" # hashDBのkeyを一覧する console2:$ tcrmgr list localhost # key"hoge"を削除する console2:$ tcrmgr out localhost "hoge"
このデータ操作の部分は、先ほどのTCを直接使う場合とほとんど同じですね。さて今の状態で、DBにはkey"hoge2"が残っているはずです。コンソール1に戻って、TTを停止します。
^C
ストレージにしていたTCがどうなっているか確認してみましょう。TCを直接操作するので、tcrmgrではなくtchmgrを使用します。
console1:$ tchmgr list casket.tch
TC上でも、key"hoge2"が残っていることが確認できたはずです。
公式にはPerlとRuby用のAPIが提供されています。Java用のAPIとしては、tokyotyrant-javaが有名です。TCのAPIに似たAPIで操作が可能です。(スライド38)
TTはレプリケーション機能を備えています。スライドでは大雑把にしか触れていませんが、レプリケーションについてはまとまった記述がなかなか見つからず苦労したので、ここはスライドから少し離れるところもありますが、詳しく解説しましょう。
仕組みとしてはMySQLとほぼ同じです。(マネして作った、と作者が書かれていました。)具体的には、
この動作を繰り返してレプリケーションが行われます。(スライド39-42)
データが無い初期状態からレプリケーションを行うのは、極めて簡単です。
それぞれ指定して起動するだけです。
問題はデータが既に存在する場合ですね。仮に、意識的な設定を何もしていないTTが既に稼働していて、突然レプリケーションをしようと思い立ったとしましょう。稼働中のTTをマスタにし、スレーブとなるTTを新たに追加することを考えます。(スライド43-46 ここをとても大雑把にしていますが)
一番気になるのはTTを停止する必要があるのかどうか、というところです。TT起動時のオプションを確認し、不幸にしてサーバID(-sid)と更新ログディレクトリ(-ulog)とが指定されていなかった場合は、TTを一度停止する必要があります。そして例えば以下のようなオプションを追加して再起動します。以降、マスタ/スレーブでの操作をプロンプトで示します。
# 更新ログディレクトリを作成 master:$ mkdir /path/to/ulog # TTを起動 master:$ ttserver -sid 1 -ulog /path/to/ulog /path/to/casket.tch
これでまずはマスタとなるTTが手に入りました。
次はDBファイルのスナップショットを作成します。先ほど説明したように、レプリケーションの鍵になるのはタイムスタンプです。DBファイルのコピーをとると同時に、そのDBファイルのタイムスタンプを知る必要があります。
そのためにはコピーのためのシェルスクリプトをマスタサーバに用意し、TTの実行ユーザに実行権限を与えます。
master:$ cat ttcopy.sh #!/bin/sh SRCPATH="$1" DSTPATH="$SRCPATH.$2" cp -f "$SRCPATH" "$DSTPATH"
その上で以下のコマンドを発行すると、マスタサーバ上にDBファイルのコピーが作成されます。コピー中はTT全体がロックされることに注意してください。
someconsole:$ tcrmgr copy master.host '@/path/to/ttcopy.sh'
master:$ ls -l /path/to/dbdir/ -rw-r--r-- 1 ttserver ttserver 528704 12 11 18:40 casket.tch -rw-r--r-- 1 ttserver ttserver 528704 12 11 18:40 casket.tch.1323596455089588
元のDBファイル名に数字が付いたファイルが出来ていますね。この数字がDBファイルのタイムスタンプです。
先ほどコピーしたDBファイルをスレーブサーバに移動させ、タイムスタンプファイルを作成します。
# DBファイルの末尾についたタイムスタンプを.rtsファイルに書く slave:$ echo "1323596455089588" > slave.rts # DBファイル名からタイムスタンプを除去する slave:$ mv casket.tch.1323596455089588 casket.tch
そして例えば以下のようなオプションを付けて、スレーブとなるTTを起動します。
slave:$ ttserver -sid 2 -mhost master.host -mport 1978 -rts /path/to/slave.rts /path/to/casket.tch
これでレプリケーションが開始されました。
今回はスライドを基にTokyo CabinetとTokyo Tyrantの基本と、まとまった情報の少ないTokyo Tyrantのレプリケーションについて解説・補足しました。他のkey-valueストアについても言えることですが、(あくまでRDBMSではないという意味で)限定された状況下では高いパフォーマンスを発揮します。使いどころ次第で便利に使えます。
ところで、昨年5月にTokyo Cabinetの後継となるKyoto Cabinetがリリースされています。Tokyo製品群についても継続してメンテナンスはしていくと表明されているので、まだしばらくは使っていても大丈夫でしょう。機会(と時間)があればKyoto製品群にも触れてみようと思っています。