« Back to Home

Tokyo CabinetとTokyo Tyrant

Tokyo CabinetとTokyo Tyrantについて、社内勉強会のために作ったスライドをSlideShareに公開しました。(スライドはKeynote形式でダウンロード可能です)その解説と補足をしておきます。勉強会の目的は、Tokyo CabinetとTokyo Tyrantを大づかみに理解することと、実際にデータ操作をしてみることでした。

http://www.slideshare.net/akirakoyasu/tokyo-cabinet-tokyo-tyrant-10468880

まずはTokyo Cabinet/Tokyo Tyrantとは何なのか、端的に言えば、

Tokyo Cabinet
ファイルDB
Tokyo Tyrant
Tokyo Cabinetを内包したサーバ

ということになります。(スライド2-8)

Tokyo Cabinet

Tokyo Cabinet(以下TC)はいわゆるkey-valueストアで、4種類のデータ構造を持つことができます。(スライド10-17)

hash
拡張子.tchで示されます。1つのkeyに対して1つのvalueを保持する、単純なマップです。
b+ tree
拡張子.tcbで示されます。1つのkeyに対して複数のvalueを保持します。
fixed-length
拡張子.tcfで示されます。hash同様に1つのkeyに対して1つのvalueを保持しますが、「keyは自然数である」「valueは最大長をもつ」という制約があります。
table
拡張子.tctで示されます。1つのkeyに対して、名前付きの複数のvalueを保持します。

Tokyo CabinetのCLI

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ページを参照してください。

Tokyo CabinetのAPI

TCの操作はネイティブライブラリとして提供され、また、他のプログラム言語から使用するためのAPIが提供されます。基本的に先ほどのCLI(正確にはネイティブライブラリ)に準ずるメソッド・オプションとなるよう作られています。スライドではJavaAPIの例を挙げています。(スライド25)

Tokyo Tyrant

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"が残っていることが確認できたはずです。

Tokyo TyrantのAPI

公式にはPerlとRuby用のAPIが提供されています。Java用のAPIとしては、tokyotyrant-javaが有名です。TCのAPIに似たAPIで操作が可能です。(スライド38)

レプリケーション

TTはレプリケーション機能を備えています。スライドでは大雑把にしか触れていませんが、レプリケーションについてはまとまった記述がなかなか見つからず苦労したので、ここはスライドから少し離れるところもありますが、詳しく解説しましょう。

仕組みとしてはMySQLとほぼ同じです。(マネして作った、と作者が書かれていました。)具体的には、

  1. スレーブサーバはレプリケーションのタイムスタンプを保持しており、それを自身のサーバIDと共にマスタサーバへ通知する。
  2. マスタサーバは、通知されたタイムスタンプより後、かつ通知されたサーバID以外の更新ログをスレーブへ送信する。
  3. スレーブサーバは更新ログを適用し、レプリケーションのタイムスタンプを更新する。

この動作を繰り返してレプリケーションが行われます。(スライド39-42)

初めからレプリケーションを開始する場合

データが無い初期状態からレプリケーションを行うのは、極めて簡単です。

それぞれ指定して起動するだけです。

途中からレプリケーションを開始する場合

問題はデータが既に存在する場合ですね。仮に、意識的な設定を何もしていないTTが既に稼働していて、突然レプリケーションをしようと思い立ったとしましょう。稼働中のTTをマスタにし、スレーブとなるTTを新たに追加することを考えます。(スライド43-46 ここをとても大雑把にしていますが)

1)マスタサーバを設定する

一番気になるのは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が手に入りました。

2)DBファイルをコピーする

次は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ファイルのタイムスタンプです。

3)スレーブサーバを起動する

先ほどコピーした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製品群にも触れてみようと思っています。