So-net無料ブログ作成
  • ブログをはじめる
  • ログイン

インフラエンジニアのためのkumofs情報 CASを試す [kumofs]

kumofsはCAS(Compare-And-Swap)をサポートしています。これは、ある値を更新したい
場合に、他のプロセスが同時に更新しようとして競合が発生してしまうのを防ぐしくみ
です。具体的には、ひとつのプロセスが値を更新しようとしたとき、内部でその値に関連
付けられたバージョン番号を同時に取得して、書き込み時にバージョン番号を比較、同じ
であれば値を更新します。そしてバージョン番号も変わります。
バージョン番号が一致しなければ、他のプロセスが値を更新していることになるので、値の
取得からやり直します。
実際に試してみます。
まず、CASを使わないで2つのプロセスから同時に一つの値を更新してみます。
以下のようなrubyサンプルを作ります。
一つのvalueを、引数に与えた数だけひたすらカウントアップするカウンターです。
for i in 1..ARGV[0].to_i do
  value = mem.get('counter',true)
  value = value.to_i + 1
  mem.set('counter',value,0, true)
end

実行前に、キー「counter」にvalueとして「0」を入れておきます。
$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set counter 0 0 1
0
STORED

2つのプロセスとして起動して、同時にvalueを更新してみます。
$ ./counter.rb 10000 &
$ ./counter.rb 10000 &

結果を見てみると、
$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is ']'.
get counter
VALUE counter 0 5
11184
END

となり、合計20000にはなっていません。
更新が競合し、ひとつのプロセスが更新した結果を、他のプロセスが読み直しをせずに
自分の値で上書きしてしまったため、値が小さくなってしまってます。
次にCASを使って更新してみます。
for i in 1..ARGV[0].to_i do
  begin ret = mem.cas('counter',0,true) do |value|
      value.to_i + 1
    end
  end until ret == "STORED\r\n"
end

mem.cas()は、do~endまでのブロックで定義された操作を、あらかじめ取得しておいた
バージョン番号と現在のそれと比較し、一致すれば値(ここではvalue)を書き込みます。
書込みが正常に行われると、「STORED」を返します。「STORED」以外の値が返ってくる
場合は、valueの取得とブロック内の処理をやり直して、再度バージョン番号の比較を
して書き込みを試します。
実行してみましょう。
$ ./cascounter.rb 10000 &
$ ./cascounter.rb 10000 &

結果は、
$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is ']'.
get counter
VALUE counter 0 5
20000
END

無事、合計が20000になりました。
テストに使用した、サンプルスクリプトは以下を参照。
http://github.com/so-net-developer/kumofs/blob/master/counter.rb
http://github.com/so-net-developer/kumofs/blob/master/cascounter.rb
実行には、ruby用のmemcacheライブラリmemcache-client(1.8.5)が必要です。
$ sudo gem install memcache-client



この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は180日以上新しい記事の更新がないブログに表示されております。