ROMAにはlogとは別に指定したコマンドの実行履歴を記録するwrite-behind機能があります
設定方法
方法その1(起動後にコンソールから指定)
コマンド
wb_command_map {:command=>x}
Example
> wb_command_map {:set=>1, :delete=>2}
{"localhost_10002"=>"{:set=>1, :delete=>2}", "localhost_10001"=>"{:set=>1, :delete=>2}"}
> stat wb
stats.wb_command_map {:set=>1, :delete=>2}
方法その2(configファイルで指定)
config.rbに記述してしまえば、起動毎に設定をしなおす必要がなくなります
以下の1行をconfig.rbに追加する
WB_COMMAND_MAP = {:set=>1, :delete=>2}
この指定をした状態でsetやdeleteコマンドが実行されると、それらの実行履歴を指定したwbディレクトリに出力します
write-behindファイル
write-behindの出力先はconfig.rbで指定できますが、デフォルトの場合はカレントディレクトリにwbディレクトリが作成されています
ファイル内容
内容はバイナリで保存されています
例えば以下のような処理をした場合、
> set foo 0 0 3
bar
STORED
> delete foo
DELETED
> set foo 0 0 4
> fizz
STORED
write-behindファイルを内容はvim等で直接開くと以下のようになります
(実際にファイルに出力されるにはタイムラグがあります。balseでクラスターを終了させるとその時点のwrite-behindの内容をすぐにファイル出力します)
Vx<9e>,^@^A^@^@^@^Cfoo^@^@^@^CbarVx<9e>?^@^B^@^@^@^Cfoo^@^@^@^CbarVx<9e>C^@^A^@^@^@^Cfoo^@^@^@^Dfizz
バイナリ変換
Array => Binary
ROMA側では以下のようにbinary化しています
[t.to_i, cmd, klen, key, vlen, val].pack("NnNa#{klen}Na#{vlen}")
https://github.com/roma/roma/blob/master/lib/roma/write_behind.rb#L56
- N: ネットワークバイトオーダー(ビッグエンディアン)のunsigned long
- n: ネットワークバイトオーダー(ビッグエンディアン)のunsigned short
- a*: ASCII文字列(null文字を詰める)
Binary => Array
binaryのままで使用する場合はこのままでよいですが、arrayに戻したい場合は以下のような感じで再変換します
def read_wb(fname)
ret = []
open(fname, 'rb') do |f|
until f.eof?
b1 = f.read(10)
last, cmd, klen = b1.unpack('NnN')
key = f.read(klen)
b2 = f.read(4)
vlen = b2.unpack('N')[0]
val = f.read(vlen)
ret << [last, cmd, key, val]
end
end
ret
end
puts read_wb(#{wbファイル名})
ちなみに上のwbファイルを再変換すると、以下のように出力されます
1450745528 # 実行日時(UNIX_TIME)
1 # configで指定したコマンド番号({:set=>1, :delete=>2}なので今回はset)
foo # key
bar # value
1450745535
2
foo
bar
1450745543
1
foo
fizz
prevオプション
コマンドを指定する際にシンボルにサフィックス(__prev)を追加することでコマンド実行前のデータも出力できます
例
WB_COMMAND_MAP = {:set=>1, :delete=>2, :set__prev=>3, :delete__prev=>4 }
このwrite-behind機能を使えば、Oracleののように何日に処理したデータを限定して読み出したり、一定期間中のデータの変更推移などが集計しやすくなる