ひとりでやるRiak Advent Calendar 2012 day5 - REST API編

さて今日はREST API編。今日から三日間は今日のセミナーで離した内容を引っ張れるのでいささか楽であります(スライド)。RESTといってもPUTとかGETとかDELETEしたら終わりだと思ってるアナタ、僕もそう思ってたよ!しかし現実はそんなに甘くない。

World line

PUT

Riakは当然立ち上げた?いえーい常識だね。まずは http://localhost:8098/ping でOKが返ってくることを確認しよう。

$ curl http://localhost:8098/ping
OK

OKがきたかな?OKなら準備OKだ。こんどは サンプル画像その1をダウンロードしてriak.pngという名前で保存しておこう。次にサンプル画像その2を、右クリックからそのままtest_image.jpgという名前で保存しておこう。そして、これらの画像をRiak上に保存だ。

$ curl -X PUT http://localhost:8098/buckets/image/keys/riak.png -H "content-type: image/png" -T riak.png
$
$ curl -X PUT http://localhost:8098/buckets/image/keys/test_image.png -H "content-type: image/jpeg" -T test_image.jpg
$

さてcurlが面倒なのは成功したかどうかやエラーコードを特に表示しない。なのでそのまま画像をブラウザで開いてみて確認する。

GET

$ open http://localhost:8098/buckets/image/keys/riak.png
$ open http://localhost:8098/buckets/image/keys/test_image.png

さて無事に画像は表示されただろうか。



画像はいかがだっただろうか。

今日スベるのが怖くて出せなかったネタ

f:id:kuenishi:20121206011717j:plain

Siblings

さて、ひと通りご堪能いただけただろうか。実はこのままだと、QuorumとLast write winsというベタなConcurrency control戦略になってしまって別に何の面白みもない。もしクラスタがネットワークセパレーションで真っ二つにされてしまったらそのまま真っ二つになってデータは光錐の向こうへ消えてしまうだろう。並行宇宙の彼方に行って歴史は完全にブランチしてしまう。
別のものになってしまった並行宇宙が再び出会うとき何が起こるのか?それにはVector Clocksというものが鍵になるのでまずは@itawasaのスライドを見ていただきたい。

ちょっと何を言ってるのかわからないかもしれないが耐えて読み進めてほしい。

まずはVector Clocksを使うために、etc/app.configを次のように変更する。つまり riak_core のセクションに次の一行を挿入してほしい。

    {default_bucket_props, [{allow_mult, true}]},

デフォルトのapp.configにはdefault_bucket_propsのエントリはないはずなので、躊躇することなく書き加えてほしい。書き加えたら、再起動

 $ bin/riak stop && bin/riak start

さてこれでVector Clocksが有効になっているはずだ。とりあえず結果を見ずに二回PUTしてみる

$ curl -X PUT  http://localhost:8098/buckets/hoge/keys/hage -d "mama"
$ curl -X PUT  http://localhost:8098/buckets/hoge/keys/hage -d "papa"
$ curl  http://localhost:8098/buckets/hoge/keys/hage
Siblings:
4nERQIh7u3oNhfgTt9rVHM
5SZllErj501IVtMiUoCy7l

おおお、なんじゃこりゃあSiglingとは英語で兄弟みたいなそういう意味の言葉なので、つまりはこれが並行世界というものなのだろう。ちなみにDELETEを投げつけると無条件で消えてくれたりする。特定のSiblingを見たいときはURLの最後に "?vtag=" みたいにつけておけばBodyを見ることができる。ネットワーク切断してたら容赦なくこのどちらかが見えていたことになる。適当なものをPUTすればするだけSiblingは増えていってどうにもならないので、もう一度ちゃんと見てみる

 $ curl -v http://localhost:8098/buckets/hoge/keys/hage
 * About to connect() to localhost port 8098 (#0)
 *   Trying 127.0.0.1...
 * connected
 * Connected to localhost (127.0.0.1) port 8098 (#0) 
 > GET /buckets/hoge/keys/hage HTTP/1.1 
 > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0  OpenSSL/0.9.8r zlib/1.2.5
 > Host: localhost:8098
 > Accept: */*
 > 
 < HTTP/1.1 300 Multiple Choices
 < X-Riak-Vclock: a85hYGBgzGDKBVIcypz/fgbsTTyawZTIlMfKkPHf+BRfFgA=
 < Vary: Accept, Accept-Encoding
 < Server: MochiWeb/1.1 WebMachine/1.9.2 (someone had painted it blue)
 < Last-Modified: Wed, 05 Dec 2012 17:24:56 GMT
 < ETag: "2kbM3DorCQeJGC65A3GwOs"
 < Date: Wed, 05 Dec 2012 17:26:45 GMT
 < Content-Type: text/plain
 < Content-Length: 56
 < 
 Siblings: 
 4nERQIh7u3oNhfgTt9rVHM
 5SZllErj501IVtMiUoCy7l
 * Connection #0 to host localhost left intact
 * Closing connection #0

結局なにをしたらよいかというと、

X-Riak-Vclock: a85hYGBgzGDKBVIcypz/fgbsTTyawZTIlMfKkPHf+BRfFgA=

というのがVector clockなので、こいつを使ってCAS的なことをしようとしているようだ。つまりGETで得られたこれをそのままPUTに渡すことによって、Siblingsの値が変わっていないことを検出する。変わっていなければSiblingsを全て消してPUTされたものを残す。このVclockが一致していないとRiakは500を返すようになっている。あー不思議だ。

$ curl -X PUT  http://localhost:8098/buckets/hoge/keys/hage -H "X-Riak-Vclock: a85hYGBgzGDKBVIcypz/fgbsTTyawZTIlsfKsJvB5BRfFgA="  --data  "外道父"
$ curl http://localhost:8098/buckets/hoge/keys/hage
外道父%

これで並行世界はちゃんとひとつの世界に収束したとさ。ちゃんちゃん。

ちなみに

ネットワーク切断なんかでこの並行世界の収束に失敗すると何が起きるかというと別に大したことはなくて消えた兄弟は消えるし、マージされたやつもまた兄弟みたいなそんな感じになります。

まだスコッチ残ってるけど、そんじゃーね。