Riak Meetup Tokyo #4 その後の運用の話という記事が出てきて、わりとカジュアルな運用の場合だとあれだけでも十分かもしれない。のだけど、本当はもっといろんなことができて、いろんなことに対応できるのでその基本的な扱い方や考え方をいま流行りのQiitaというやつにまとめてみた。
ちなみに https のベンチマーク、 Riak では Erlang/OTP の crypto のSSLを使っているはずなので速いかといわれたらまあお察しください…という話かと思われる。
Riak Meetup Tokyo #4 その後の運用の話という記事が出てきて、わりとカジュアルな運用の場合だとあれだけでも十分かもしれない。のだけど、本当はもっといろんなことができて、いろんなことに対応できるのでその基本的な扱い方や考え方をいま流行りのQiitaというやつにまとめてみた。
ちなみに https のベンチマーク、 Riak では Erlang/OTP の crypto のSSLを使っているはずなので速いかといわれたらまあお察しください…という話かと思われる。
Erlang アドベントカレンダー 2014の23日目の記事です。
Erlang/OTPでアプリケーションを書いていると、システムを冗長化するために複数ノードでうまく協調動作するようにさせるために、Distributed Erlangの上に構築されたFailoverやTakeoverを使う場面がいずれ出てくる。しかし、これらの仕組みは、Riakのようにシステムをスケールアウトさせたい場合には不十分だ。スケールアウトするシステムの本質は
の3点がサポートされていることだ。これだけだといろんなものが該当するが、 Riak風に翻訳すると
ということになる。よくよく読むと、扱う対象が、実はKVSである必要がないということだ。 Riak というデータベースの構成は、 Riak Core という分散フレームワークの上に載った Riak KV というアプリケーションであるということだ。 Riak KV は Riak Core 上で動作することを前提としているが、 vnode の動作は単なるローカルのKVSである(ちょっとRiak Coreの機能を使っている)。つまり、 Riak Core という分散フレームワークを使えばあなたのアプリケーションをvnodeに乗せてスケールアウトできるようになる!というわけである。絵でいうとこんな感じだ。
ちょっと調べたところRiak以外でも(驚くべきことに!)いくつか使われているようで、最大のクラスタはOpenXの125台のもののようだ。
他にも、Riakの中だと riak_pipe というMapReduceのためのサブシステムがRiak Coreの上に分散アプリケーションとして載っている。
もうちょっというと、いままで Erlang node というものにアプリをくっつけていろいろ扱ってきたものを、間にひとつ vnode というものを挟むことになる。 vnode にアプリをくっつけて分散配置するのだ。手書きの温もりあふれる絵でかくとこうなる。
Riak Core の用語では、リクエストは「 command 」になる。Erlangのコードの中で vnode に対してコマンドを投げるとそれを実行して、結果を返してくれるというイメージだ。どの vnode にコマンドを投げるべきかは、キーを渡してハッシュを計算すると vnode のIDが返ってくるようになっている。 "riak_core_util:chash_key/1" という関数がそれにあたる。
> DocIdx = riak_core_util:chash_key({spam, ham}). <<220,127,3,124,116,114,28,36,44,206,203,237,43,32,170,68,62,127,127,133>>
この関数の中は決定論的で特に副作用はないので*1、何度実行しても同じ値が返ってくる。Consitent Hashingでいうところのハッシュ値だ。これを使って Preference List をつくる。みっつめの引数は、 Riak Core アプリケーションの名前だ。ここではRiakを使っているので、 riak_kv という名前を使う。
> riak_core_apl:get_apl(DocIdx, 3, riak_kv). [{1278813932664540053428224228626747642198940975104, 'riak@127.0.0.1'}, {1301649895747835411525156804137939564381064921088, 'riak@127.0.0.1'}, {1324485858831130769622089379649131486563188867072, 'riak@127.0.0.1'}]
2番めの引数は何個冗長化したいかという(合計でなんこの vnode にアクセスしたいのか?という)意味だ。これで、3つの vnode のIDと、それを持っているノードが判明する。あとはこれをもとに、 riak_core_vnode_master:command/4 を使えば vnode の handle_command が呼び出されて、アプリケーション特有の処理をすることができる。
いくつかのコールバックを作成することで、 vnode の各種操作ができるようになる。アプリケーション毎に冗長性や移動、転送などのセマンティクスは異なるだろうから、アプリ側で作りこんでやる必要がある。簡単なコールバックで抽象化されていることから、難しい作り込みをしなくて済むようになっている。
図のように、たとえばあるノードが故障なりダウンなりしていてそのノードが持っている vnode にアクセスできなかったとしよう。Riak Coreでは、この故障を検知して一時的にリストから外して、代替の vnode を用意する仕組みが用意されている。図のように V' にコマンドをフォールバックして別のノードで処理を代替させることができる。そのときも、本来存在しないはずの vnode を一時的に作成してセマンティクスを変えないで済むようになっている。
この代替処理のせいで、ネットワーク切断なんかのときはデータがdivergeしてしまうのだけど、そういうのも上手く処理するためのベクタークロック( vclock.erl )も用意されているので利用することができる。
つまり、Riakの高可用性の中心的な機能はフレームワークとして切り出されているので、Riak Coreを使えば誰でも高可用な分散アプリケーションを書けるようになるというわけだ。たとえば分散キューをほしいと思っている人は一部にいるだろうけど、OpenXはRiak Coreを使って広告表示フレクエンシーカウンターを作っている。噂によるとかなりの大きさのクラスタになっている(推測が正しければ、上記で出てきた125台のクラスタのことだと思うんだけど…)。
riak_core_console.erl をみれば分かるのだが、Riakの cluster コマンドはほぼ全てこのモジュールにある関数を呼んでいるだけである。つまり、 vnode に紐づくアプリを実装して、各種 handle_* のコールバックを実装していけば、自動的にノードの追加、削除、変更などの各種操作のコンソールも作成できるのである。これと clique と以前紹介した node_package を使えば、それっぽく動く分散アプリケーションを構築することができるようになっている。そいつのテストは riak_testで自動化 してしまえばよい。これで、スケールアウトや冗長化の難しいところ、面倒なところをほとんどがフレームワークで済ませられるので、開発者は分散まわり以外のアプリケーションの本質的な部分に集中できるという寸法だ。もちろん動作やアップデートは正しく理解して追っていかなければいけないが、自分でつくり上げて苦労するよりは随分楽だろう。
4年ほど前にJubatusというスケールアウトさせたいソフトウェアがあった。当時ぼくが直面していた問題は、機械学習のコアモジュールをどうやってDHTに乗せて分散させるかというものだった(BigTable風にヒエラルキアルな分散するシステムも同時期に開発していたが、わりとしんどかったのでDHTをやってみようと思っていた)。そのときコレを知っていれば(そしてC++と親和性があればナア)と、Bashoに入ってから歯痒い思いをしたものであった。
Riakが利用している分散アプリケーション開発用のフレームワーク、Riak Coreの紹介をした。こういったことにどっぷり浸かりたい方は是非、わたしの職場で一緒にハマりましょう。
*1:いろんなコンテキスト的情報を利用するのでピュ〜ア〜ではない
Erlangアベドントカレンダー16日目の記事。CROSS 2014で分散システムのテストがどうのという話になったときにぼくは riak_test をちょっとだけ話したが、それをもうちょっと詳しく説明しておこうと思う。ちなみに2年前もちょっとだけ紹介していた。
BashoがRiakのインテグレーションテストを自動化するために開発したテストフレームワークだ。 eunit や ct では機能が不十分なので結局自分たちで作ってしまった。ペネトレーションテストとか負荷テストはまた別途。
というわけで、Riakそのもののテストにも使っているが、実はRiakを使ったアプリケーション(Riak CS)の結合テストも riak_test で書かれている。
まずはコマンドを用意しよう。 17系のErlangで動くかどうかは知らない…
$ git clone git://github.com/basho/riak_test $ cd riak_test && make $ sudo cp riak_test /usr/local/bin
これで riak_test をコマンドとして実行できるようになる。
フレームワークそのものをいきなり使うのは大変なので、手っ取り早く動かしてみたいという人は(僕がいつもやっている) Riak CS のテストを走らせてみるとよいだろう。 README をもとに環境を用意して、ぜひ動かしてみてほしい。
rtdev.erl や rt_cs_dev.erl を見るとわかる。分かりませんね、本当は behaviour で丁寧に用意すべきコールバックを用意すべきなのだが、まあそうなってないのはいつものBashoクオリティということでひとつ。このなかの setup_harness や stop_all (うろ覚え)がコールバックになっていて、これらを設定してやるとハーネスとしてなんとか動き始めるはず。はず…。
以下は、ざっくりとした環境の構成を説明する。設定ファイルをつくる。設定ファイルはデフォルトでは ~/.riak_test.config だ。
{default, [ {rt_max_wait_time, 180000}, {rt_retry_delay, 1000} ]}. {rtdev, [ {rt_deps, ["/home/kuenishi/src/riak/deps"]}, {rt_retry_delay, 500}, {rt_harness, rtdev}, {rtdev_path, [{root, "/tmp/rt"}, {current, "/tmp/rt/current"}, {"1.2.1", "/tmp/rt/riak-1.2.1"}, {"1.1.4", "/tmp/rt/riak-1.1.4"}, {"1.0.3", "/tmp/rt/riak-1.0.3"}]}, {basho_bench, "/home/kuenishi/src/basho_bench"} ]}. {rt_cs_dev, [ {rt_project, "riak_cs"}, {rt_deps, [ "/home/kuenishi/cs-2.0/riak_cs/deps" ]}, {rt_retry_delay, 500}, {rt_harness, rt_cs_dev}, {build_paths, [{root, "/home/kuenishi/rt/riak"}, {current, "/home/kuenishi/rt/riak/current"}, {previous, "/home/kuenishi/rt/riak/riak-1.4.10"}, {ee_root, "/home/kuenishi/rt/riak_ee"}, {ee_current, "/home/kuenishi/rt/riak_ee/current"}, {ee_previous, "/home/kuenishi/rt/riak_ee/riak-ee-1.4.10"}, %%{ee_root, "/home/kuenishi/rt/riak_ee_onefour"}, %%{ee_current, "/home/kuenishi/rt/riak_ee_onefour/current"}, {cs_root, "/home/kuenishi/rt/riak_cs"}, {cs_current, "/home/kuenishi/rt/riak_cs/current"}, {cs_previous, "/home/kuenishi/rt/riak_cs/riak-cs-1.5.1"}, {stanchion_root, "/home/kuenishi/rt/stanchion"}, {stanchion_current, "/home/kuenishi/rt/stanchion/current"}, {stanchion_previous, "/home/kuenishi/rt/stanchion/stanchion-1.5.0"} ]}, {test_paths, ["/home/kuenishi/cs-2.0/riak_cs/riak_test/ebin"]}, {src_paths, [{cs_src_root, "/home/kuenishi/cs-2.0/riak_cs"}]}, {lager_level, debug}, {build_type, oss}, %%{build_type, ee}, %%{flavor, {multibag, disjoint}}, {sibling_benchmark, [{write_concurrency, 16}, %% seems not working more than 20 {duration_sec, 100}, {leave_and_join, 3}, %%{version, previous}] {version, current}] %%] }, {flavor, basic}, {backend, {multi_backend, bitcask}} ]}. {rt_cs_dev_old, [ {rt_project, "riak_cs-1.5"}, {rt_deps, [ "/home/kuenishi/cs-1.5/riak-ee-1.4.10/deps", "/home/kuenishi/cs-1.5/riak_cs/deps", "/home/kuenshi/cs-1.5/stanchion/deps" ]}, {rt_retry_delay, 500}, {rt_harness, rt_cs_dev}, {build_paths, [%%{root, "/home/kuenishi/rt/riak"}, %%{current, "/home/kuenishi/rt/riak/current"}, {root, "/home/kuenishi/rt/riak_ee_onefour"}, {current, "/home/kuenishi/rt/riak_ee_onefour/current"}, {ee_root, "/home/kuenishi/rt/riak_ee_onefour/"}, {ee_current, "/home/kuenishi/rt/riak_ee_onefour/current"}, {cs_root, "/home/kuenishi/rt/riak_cs"}, {cs_current, "/home/kuenishi/rt/riak_cs/current"}, {stanchion_root, "/home/kuenishi/rt/stanchion"}, {stanchion_current, "/home/kuenishi/rt/stanchion/current"} ]}, {test_paths, ["/home/kuenishi/cs-1.5/riak_cs/riak_test/ebin"]}, {src_paths, [{cs_src_root, "/home/kuenishi/cs-1.5/riak_cs"}]}, {lager_level, debug}, {build_type, oss}, {flavor, basic}, {backend, {multi_backend, bitcask}} ]}.
長かった。ここでは3つのアプリケーションのテストがセットアップされている。それぞれ長さ2のタプルであるが、ひとつめの要素はテストの名前だ。これを使ってテストを呼び出す。このファイルだと、 rtdev, rt_cs_dev, rt_cs_dev_old が用意されている。ひとつめは Riak のテストだ。ふたつめは現在開発中の Riak CS のテスト、みっつめは現行バージョンの Riak CS 1.5 系のテストだ。Riakのテストをサンプルに、各設定を説明しよう。
実際のテストコードはとても単純だ。 confirm/0 という関数がエクスポートされていることが動作条件だ。この関数の spec は
-spec confirm() -> pass.
というとても単純なもので、なにかテストがコケたら例外でもbadmatchでも何でも飛ぶので、それを上で自動でキャッチしてくれる。 pass というアトムを返せば成功したことになる。どんなアサーションを入れても大丈夫だ。
$ ls /path/to/your/test-beams foo_test.beam bar_test.beam $ riak_test -c rt_your_dev -d /path/to/your/test-beams || とすると、 foo_test と bar_test.beam を実行する。ピンで実行したかったら、 >|sh| $ riak_test -c rt_your_dev -t foo_test
とする。
Giddyupというモノがある。これはいわゆる「スコアカード」というやつだ。 riak_test の実行結果は環境によって変わるだろうから、それらの結果を一覧表示してどこがダメかに早めに気付けるようにしている。ちなみに Riak CS では使ってないので、よく知らないです…やらなきゃダメなんだけれども。
研究会が設立されるとか、前からそういう流れになるとは聞いていたが、今日(11日)に開催されたビッグデータ基盤技術勉強会に参加して発表してきた。招待してくれた川島先生には感謝しかない。それにしてもあれ研究会じゃないの、ビッグデータとかいまさら冠するなんて、なんというダサいネーミングセンスなんだと思ってはいけない。世間がやっと俺たちに追い付いてきたんだから、ダサいと思ってはいけない。飽きたころに慣れたものをやめてサッサと次に行っていいのは式年遷宮だけだ。
ぼくの発表もなるべく復習に徹して、研究会だからなにか新しいことを言わなくてもいい、インダストリアル枠だしわかってることを解説していこうというスタンスで解説した。詳細を省いているところも、語弊があるところもあるがお許しいただきたい。
さて丸一日盛り上がってワイワイやった後に、吉祥寺で本番の会があって、そこでまた(いつもの)いろんな人と話した。そこで川島先生と、僕の日本のデータベースコミュニティが盛り上がらないのはよいシステム系の講義がないという主張の話になった。「あしたの授業でそういう話するけど、どんな話したらいいと思います?」という話になったので、そこで伝えたんだか伝えてないんだかよく覚えてないんだけど考えをここにまとめておこう。
有名なものだとUCBのCS262があって、これはアメリカだとどこの大学でも同じ番号がつくようになっているのかな?基本的にはこれを半期やるだけでも全然違うのだけど、これが知ってる限り理想的かな。ちょっと検索してみただけでもいくつかある。
あとは、分散系もひと通り理論は聞きかじっておいたほうがよくて、やはりNancy Lynchの分散アルゴリズムの講義は、他に選択の余地がない感じ。佐藤先生がいう通り、用語がクラウドまわりと若干ズレていたり、実装なんか関係ねーよ!というガチ感はあるのだけど…プログラミングの世界でいうSICPみたいなものか。MITはそもそもElectrical Engineering and Computer Scienceの学科のOCWがガチすぎて目移りしてしまうね。
ここまで来たらあなたもいっぱしに知ってると語れるはず。次は論文をガンガンと読んでいこう。僕の同僚のReading Listが、贔屓目に見なくても分散まわりをきちんとまとめていて流れを抑えている。最近はSparkやらTezやらKafkaやらいろいろと目移りするように新しいソフトウェアが登場しているが、このReading Listを押さえているのと押さえていないのでは理解度が全然違う。
これは、質問されてから思いついたのだが、単にアメリカでされているようなトピック、内容の講義を真似しても意味がないというか、(僕がそうだったように)日本の大学生はそのレベルからスタートできないだろうという予想がある。これはどうしてだろうかと考えながら話して、…そもそも現実世界のサーバー群は分散システムなわけで、通信は本質的にAsyncronyだしPartial Failureが起きるのだけど、講義で耳で聞いてもピンとこない。そういった分散システムのモデルを講義で語るだけでなくて、デモンストレーションや思考実験で理解させるような工夫が必要なんじゃないかと提案した。
で、シャワーを浴びながら考えたのは、そういう学生実験がないことに思い至った。ぼくは大学に入った年から毎年のように何か実験がカリキュラムにあったのだけど、データベースや分散システムに関する実験がカリキュラムに組み込まれていなかった。最近はHadoopを使う何がしかの何かがあるという話も聞いているが、まあそれは使うだけだ。Hadoopを使って何かしら計算機科学について学びがあるかというと、僕はそんなにないと思う(並列処理なら、スレッドプログラミングやMPIの実験の方が学びが多い)。
あと、ひとつだけ古いんだけど良さそうな講義資料を見つけたのでここにリンクしておこう => モバイル通信プロトコル授業資料
主催側のみなさんには本当に頭が下がります。ごくろうさまでした。
この記事はErlang Advent Calendar 2014の9日目の記事です。
Erlang/OTP でサーバー作ったあとのデプロイはわりと大変だ。リリースをわりと念入りに作っておいても、ディレクトリ構造がややこしかったりいろいろと面倒らしい。ぼく自身は運良くそういう問題はこれから紹介する node_package を使っているのであまり苦労をしたことがないのだが、リリースを作る大変さはすごいE本を読めば書いてある。
これを読んで、やっぱり自分がラッキーなことを再確認した。実際、うまくツールチェインを作りこんでも、 NIF があったりしてリリースを環境ごとにコンパイルしなければいけなかったりとかなり面倒だ。で、サービスを運用している会社でもない場合、たとえばCentOSやUbuntu, Redhatなど複数の環境にインストールできるようにしなければならない。
しかしながら、ディストリビューションやOSによってパッケージシステムの設計や思想が全く異なっていて、それぞれの作法ややり方をいちから覚えて作りなおさないといけない。せっかくどんなOSでも動作するErlang VMを同梱したはずのリリースを作ったのにこれでは本末転倒だ。ほら、やっぱり設定ファイルは /etc に置きたいし、各種ツール類は /usr/sbin にインストールしたいじゃない。
その問題を解決してくれるのが node_package だ。これは Riak や Riak CS のリリースパッケージを作るために作られた便利ツールチェインだ。前提条件としては、 rebar でリリースが作れるようになっていれば、あとはこれを rebar.config に追加しておいて、 Makefile かどこかにパッケージ作成のコマンドを覚えておけば、あとは make package でどんなパッケージでも作れるようになっている。 node_package がサポートする環境の一覧は Riak のダウンロードページを見るのが正しい確認方法だ。
使い方はまあ、 Riak の Makefile の様子を見てそれなりに汲み取ってもらえれば…というのはいささか大変過ぎるだろうと思うので、まずはEUC 2013での解説スライドを貼っておこう。
簡単な手順をかいておこう。
CentOSだと rpm-build だし、 Ubuntu だと dchroot devscripts debhelper あたりが必要だろう*1。
"rebar generate" でローカルのリリースがきちんとできるように準備しておこう。この辺りはいろいろ面倒なので省略。reltools.config とか vars.overlay とかまあいつものアレをちゃんと書いて、パッケージがなくてもこのリリースがちゃんと動くようにしておこう。 node_package も含めて正しい手順を詳しく知りたい人はこちらをどうぞ→Erlang/OTP パッケージングコトハジメ
まずはモノを持ってこないと話にならない。他にも当然、 lager, eper, cluster_info くらいはリリースに入れると思うのでちょっとここでも書いておく。最新版は 2.0.0 だ。
{deps,[ {node_package, ".*", {git, "git://github.com/basho/node_package", {tag, "2.0.0"}}}, {lager, ".*", {git, "git://github.com/basho/lager", {tag, "2.0.3"}}}, {eper, ".*", {git, "git://github.com/basho/eper.git", {tag, "0.78"}}}, {cluster_info, ".*", {git, "git://github.com/basho/cluster_info.git", {tag, "2.0.0rc1"}}} ]}.
お作法としては、 package/ というディレクトリを作って、そこに改めて指定のタグなりブランチなりをクリーンな状態にして持ってきた方が余計なものが入らなくてよい。Makefileは deps/node_package/ に入っているので、これを持ってくる。
package: package/$(PKG_ID).tar.gz $(MAKE) -C package -f $(PKG_ID)/deps/node_package/Makefile package/$(PKG_ID).tar.gz: package.src package.src: deps mkdir -p package rm -rf package/$(PKG_ID) git archive --format=tar --prefix=$(PKG_ID)/ $(PKG_REVISION)| (cd package && tar -xf -) make -C package/$(PKG_ID) deps for dep in package/$(PKG_ID)/deps/*; do \ echo "Processing dep: $${dep}"; \ mkdir -p $${dep}/priv; \ git --git-dir=$${dep}/.git describe --tags >$${dep}/priv/vsn.git; \ done find package/$(PKG_ID) -depth -name ".git" -exec rm -rf {} \; tar -C package -czf package/$(PKG_ID).tar.gz $(PKG_ID)
node_package が見るための設定ファイルのようなものだ。パッケージのベースネームやライセンスの指定、インストールすべきスクリプト類、作成すべきユーザー名などいくつかの項目を指定することがでくいる。 Riak だとこんな感じになる。そこに載ってない豆知識をひとつ披露しておくと、
{deb_depends, ["nkf"]}.
みたいな感じで、依存パッケージもここで指定できたりする。
ここまでできたら、あとは簡単。
$ make package
あとは、 node_package がディストリビューションや環境を自分で判定してリリースから、その環境用のパッケージを作ってくれる。リモートのレポジトリにきちんとタグがついていれば、そのタグを使ってバージョン番号をよしなにパッケージにつけてくれるし、そうでなければ git のコミットハッシュを使ってユニークな番号をつけてくれる。
コツは rebar.config でちゃんとバージョンを固定しておくことだ。依存ライブラリが多すぎて毎度タグを打つのが面倒な場合は rebar_lock_deps_plugin を使うとよいだろう。
1番簡単に作れるものとしては、やはり Riak CS を推したい。もしも Riak CS がサポートするLinuxやFreeBSD、MacOSなどの環境を持っているようであれば、Erlang (R16B03-1) をインストールした
あとにコレを試していただきたい。(CentOSやUbuntuだとパッケージ作成系のパッケージも必要)
$ git clone git://github.com/basho/riak_cs -b release/1.5 $ cd riak_cs && make package ...(snip) make[2]: Leaving directory '/tmp/riak_cs/package' make[1]: Leaving directory '/tmp/riak_cs/package' $ ls package/packages/ riak-cs_1.5.2.8.g09aa0a4-1_amd64.deb riak-cs_1.5.2.8.g09aa0a4-1_amd64.deb.sha
できた!
簡単ですね。
ぼくはこれとDockerを組み合わせて、いつでもどこでも CentOS 用のRPMパッケージを作れるようにしてある。ブランチ名を指定して make rpm とやると、それだけで修正済みのパッケージができるようになっている。せっかくなのでDockerfileを公開しておこう。こうしておけば、大規模なビルド環境がなくても Drone.io とか?ローカルでちょこっとパッケージを作ってあちこちの環境で試すことができる。 Docker Image を作っておいとけばいいではないかという話もあるが、ネットワークとIOまわりのことを気にして下回りになるべくレイヤーを挟みたくないのでやらない。
これをちょっと応用して、わりとパッケージを作りにくい、 escriptize されたツールもRPMなどのパッケージを作れるようにもしてある。最近だと、 basho_bench のRPMが急遽必要になったのでこれでRPMパッケージをサクッと作ってリリースした。他にも、特定のユーザー向けの簡単なErlangツールもこれでパッケージにしておくと、Erlangで書かれたとか、使うためにErlangをインストールしなきゃいけないとか面倒なことを考えなくてよいし、こちらも説明の手間が省けている。本当に便利すぎる。
この node_package すこぶる便利なのだが、いくつかイケてないところもある。 /usr/share に入れるようなドキュメント類(リリースノートやライセンス、や manpages なんか)も一緒にうまく入ればよいのだが、そのあたりは全く機能がない(Riakでは docs.basho.com に全てドキュメントを公開してしまっているので困ってない)。あと、 release upgrade には対応していない。というか、この手のパッケージ管理と release upgrade ってすごく相性が悪いので…というわけで、この辺りをうまくこなしてくれる猛者がいたら、こちらか、こちらまでどうぞ!
*1:よくわからないのでとりあえず入れている
この記事は Erlang Advent Calendar 2014 の三日目の記事です。
MessagePackというシリアライゼーションのフォーマットがある。これはまあまあ有名じゃないかもしれないけど、今をときめく fluentd の裏側で使われているプロトコルだ。この手のシリアライザは多種多様で、圧縮まで考えると歴史的にも沢山あって死屍累々の歴史でもある。モダンなやつだとAvro, Thrift, ProtocolBuffers などがあるが、サイズ、速度、柔軟性のバランスを考えるとかなり独特な位置にある。興味があるひとはTwitterでMessagePackってつぶやいてみると作者たちが釣れるかもしれない。今日はこの Erlang/OTP での実装について話をしよう。
基本的にはこれを単体で使うことはないだろうと思うが、簡単に試したいかたは次のようにすればよいだろう。システムに Erlang/OTP (R15B ~ 17.x) と git がインストールされていることが前提だ。
$ git clone git://github.com/msgpack/msgpack-erlang $ cd msgpack-erlang $ ./rebar compile $ erl -pa ebin > Bin = msgpack:pack([<<"spam">>, <<"ham">>, <<"egg">>, 42]). <<148,164,115,112,97,109,163,104,97,109,163,101,103,103,42>> > msgpack:unpack(Bin). {ok,[<<"spam">>,<<"ham">>,<<"egg">>,42]}
他にもいくつかAPIがあり、ドキュメントはないが、関数そのものは4つしかない。 msgpack.erl をみれば概要がわかるだろう。ちなみに Erlang/OTP 専用になるが、 "msgpack:term_to_binary/1" と "msgpack:binary_to_term/1" という便利関数も用意している。これは、 MessagePack の新仕様の拡張型を使って、ErlangのTermを全部エンコードできるようにしたものだ。これを使えば、 ナマのMessagePackでサポートしているプリミティブなErlang Termはそちらに変換され、 pid() などどうにもしにくいものは t2b なり b2t に部分的にフォールバックしてくれるというスグレモノだ。ちなみにコレを使っている人はまだみたことがない。速いかどうかは知らない。
自分のErlang/OTPのソフトウェアに組み込みたいときは、 rebar.config に次のように書くとよいだろう。
{deps, [ {msgpack, "0.*", {git, "git://github.com/msgpack/msgpack-erlang", {tag, "0.3.2"}}} ]}.
こちらまで。Apache 2ライセンスに同意していただくことが必要。OSSのソフトウェアを開発する仕事をしているくせに、OSSの開発にあまり時間を割けていないというみっともない状態なので、メンテナが増えてくれると嬉しいなあ…
いま改めて検索してみると、最初の実装を発表したのは5年以上も前になる。最初のコードはわずか300行ちょっとの1ファイルで、シリアライザとデシリアライザが全部入ってしまって、Erlangのパターンマッチすげえ!と感動したのを5年ぶりに思い出せた。当時はまだ僕はErlangを始めたばっかりで…(以下ポエム)
それが、8ヶ月後には公式ライブラリの仲間入りをして…それも4年前のことであるから、思えば遠くまで来たもんだ。
11月の19,20日に開催されたWebDB Forumに参加してきた。カンファレンスそのものは、いろんな人に久しぶりに会えたり、ネット上でなんとなく知っていても話したことなかった人と話したり、意外な人の意外な一面をみることができたりと、とても楽しむことができた。立場としては所属している会社のスポンサー枠で参加して目的もあって発表もしてきたわけだが、いくつか思うところがあるのでここにまとめておきたい。
WebDB Forumと銘打ってはいるものの、データベースに関する研究発表は非常に少ない。OSやネットワーク、システム系の研究と併せても、機械学習やNLP、Webなどの技術に感心を持つ人は多く数で圧倒されている。体感では 90% だ。それをいえば別に VLDB や SIGMOD などのトップカンファレンスもデータベースの技術を直接扱うことは少ないし、データベースの要素技術は多岐にわたるので一概に定義することは難しいのだが。まあ私が興味を持てる発表が少なかったと言い換えても構わない。
学会がこのようになっているのは、当然の原因があって、そもそもデータベースを扱う研究室が非常に少ない。わたしはそんなに知っているわけではないが、インダストリアルからも見えているのは東大の喜連川研、東工大の首藤研、筑波大の川島研、最近できた阪大の鬼塚研がわずかに取り組んでいるだけだ。それもクラウドの要素技術のひとつとして、研究室の一部で…というのが実態だ。ComSysやDEIMに行けばもっと多様なものが見られるのは知っているが…
まずはいくつかのスライドをはっておく。
これがCassandra
ほかにも、 CyberAgentにおけるMongoDB や [C16] インメモリ分散KVSの弱点。一貫性が崩れる原因と、それを克服する技術とは? by Taichi Umeda など、アカデミックとは違うことが起きているのが分かるだろうか。
これは単なる人材の需給のミスマッチで説明できる現象ではなくて、そもそもこういった下回りの技術に若者たちが興味を持たないという傾向がここ十年以上続いていることが遠因だ。現に私が学生だったときも、OSやデータベース、ネットワークにまだまだ研究課題があるとは思っていなかった。それは教科書や論文の延長で考えれば確かにそうなのだけど、現実世界に引き込んだ瞬間に違うことになる*1。…のだが、その魅力に気付いたのは、私の場合は大学を出てサラリーマンになってからだった。分散システムやデータベースに出会って、自分で設計してみて、実装してみて初めて分かることがあまりに多い。とんでもなく優秀な人なら、周囲の助けも得て学部から修士の3,4年でその境地に辿り着けるだろうが、私のようなふつうの学生 はそうではなかった。
あと最近はAWS使えばそれで大抵うまく動くので別にいいよね、みたいな。身近に問題がないというのも問題なのだけど、…。
WebDB Forumで何人かアカデミックやその出身の人と話した限りでは、やはり講義が少ないという現実があって、それは学生が興味を持たないことも原因だし、教授陣があまりそっち系の講義をやっていない&できる人がいないことも原因でもある。人が集まらないのはなぜかというと、…という言葉を考えるとちょっと言葉に詰まる。
とりあえず分散システムの人はトランザクションを学ぶべきだし、トランザクションの人は分散システムを学ぶべきだ。だから、とりあえず、Bashoという会社に行くと(どっちかというと分散システムの知識にかたよるけど)両方の経験が身につくので、行ってみるといいと思うよ!
奇しくも、5年も前に 基盤系プログラマ - kuenishi's blog などという煽り記事を書いた問題がわりと近い方向であたっていて、今ではどんな会社もちゃんとしたインフラエンジニア(当時はそういう言葉がまだなかった)を欲しがっている。これからデータ量やトラフィックが益々増えていくとそういう人種の価値がますます上がるわけで、この需給のギャップを解決するためには、やっぱり最初の一歩は大学の講義が増えて「こういう技術、ものすごく金になるんですよ」とか、「本当に賢いヤツらはここに集まっている」ということを滾々ともう一度伝えていくしかないのだろうかとか最近考えている。
欧米でわぁ〜、というのはあまり言いたくはないのだが UCB の cs262 をネット上で貼ってくれている人がいたのでここでもリンクしておこうと思う。わたしもあまり多く追えてはいないのだけど、アメリカでCSの強い大学だとどこでもこのレベルの講義があって、学生がヒィヒィ言いながら履修している(という印象だ)。日本だとこういうのなかったよね、少なくとも私が学生だった頃は。
*1:某チョプリン氏がよい例だと思う