おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

ActiveRecordのようにTokyoTyrantを使う、MiyazakiResistanceを作りました

TokyoTyrantをActiveRecordのように気軽に使える、MiyazakiResistanceを作りました。Cabinet(内閣)、Tyrant(傀儡)という意味を見て、地方から傀儡政権に抵抗するというイメージが勝手にわいてきたのでした。
MiyazakiResistanceは、TokyoTyrantのテーブルデータベースを対象にしています。データスキーマのないTokyoTyrantに、あえてスキーマの制約を与えることで管理をしやすくしています。TokyoTyrantでは異なる種類のデータをひとつのデータベースに置くことはあまりないと想定してのことです(キー値がかぶるし)。
MiyazakiResistanceは、レプリケーションにも対応しています。マスターと複数のスレーブ構成でも、デュアルマスタ構成でも大丈夫です。デュアルマスタはアクティブ-スタンバイで運用することを想定していて、アクティブ側がタイムアウトしたときはスタンバイ側にフェイルオーバーします。
まだ開発中なのでバグはあちらこちらに残っているのですが、適宜解消していく予定です。
github上で公開しています。 http://github.com/tsukasaoishi/miyazakiresistance/tree/master

1.インストール(gemcutterで公開しています)

sudo gem install miyazakiresistance  

2.モデルクラスの定義

require 'rubygems'  
require 'miyzakiresistance'  
class Example < MiyazakiResistance::Base  
  set_server "localhost", 1975, :write  
  set_timeout 60  
  set_column :name, :string  
  set_column :age, :string  
  set_column :created_at, :datetime  
end  

MiyazakiResistance::Baseを継承して定義します。

set_server でTokyoTyrantのサーバーを指定します。第一引数がホスト名、第二引数がポート番号です。第三引数はオプションで指定しなければ:readonlyと解釈されます。:writeは読み書き両用のサーバーです。
マスターと複数のスレーブで構成するときは、

  set_server "master", 1975, :write  
  set_server "slave1", 1975  
  set_server "slave2", 1975  

と宣言します。読みのときにどのサーバーが選択されるかはランダムに決定されます。
デュアルマスタ構成のときは、

  set_server "active", 1975, :write  
  set_server "standby", 1975, :standby  

:standbyで指定されたサーバには、読み込みのみアクセスします。さらにフェイルオーバーの対象に指定されます。

set_timeout でタイムアウト値を宣言します。単位は秒です。タイムアウト値を超えると、対象のサーバーはコネクションプールから排除されます。対象のサーバーがマスタの場合、デュアルマスタでスタンバイが存在しているときはフェイルオーバーします。スタンバイが存在しなければ例外を吐きます。

set_columnでデータ構造を宣言します。キー値はself.idとして規約で定義されているので宣言の必要はありません。第一引数にカラム名、第二引数にデータの型を指定します。データの型は、:string(文字列)、:integer(数値)、:date(日付)、:datetime(日時時刻)の4種類です。:integerは実際には実数でも問題ありません。:dateはDateクラス、:datetimeはTimeクラスに対応しています。

実際のCRUD操作はActiveRecordとほぼ同様です。conditionsの書き方だけが少し違っていて、条件同士は必ずAND結合されるので、条件の間にAND, ORなどを書く必要はありません。

work = Example.new(:name => "tsukasa")  
work.age = 34  
work.save  
Example.count  
Example.find(:all, :conditions => ["name = ? age = ?", "tsukasa", 34], :order => "created_at DESC", :limit => 10)  

TokyoTyrantのオプティマイザは最初に型が一致したカラムのインデックスを使用します。

Example.find(:all, :conditions => ["created_at >= ? created_at <= ?", yesterday, today])  

だと、最初の created_at > ? にはインデックスが適用されますが、二つ目の条件 created_at

Example.find(:all, :conditions => ["created_at between ?", [yesterday, today]])  

とすればいいでしょう。