ソフトウェアデザイン3月号はRiakの中身を解説します

2014年3月号のソフトウェアデザインの記事は「Riakはなぜデータをなくさないか」という観点から、Riakの設計とその思想を解説する。レプリケーションを行うデータベースの一般論からはいって、書き込み競合が起きたらどうなるか、ネットワーク切断が起きたらどうなるか、整合性とは何なのか、永続化とは一体何なのか?について語る。

Software Design (ソフトウェア デザイン) 2014年 03月号 [雑誌]

Software Design (ソフトウェア デザイン) 2014年 03月号 [雑誌]

ACID的なデータベースではDurabilityはあって当たり前であるが、それではDurabilityとは何なのか?という議論もあるのだが、とりあえず、CAP定理的にはレプリカのConsistencyとAvailabilityとPartition Toleranceは矛盾する。昨今のデータベースは基本的にはConsistencyだけにフォーカスしていて、Consistencyを守るためにAvailabilityとPartition Toleranceを犠牲にしている場合が多い。RiakはConsistencyの定義を変えることでAvailabilityとPartition Toleranceを同時に実現しているのだけども、その中でもAvailabilityと、Durabilityの話が中心に進んでいく…というとなんだかカッコイイですね!

これを執筆した後に筑波大学での講演があったのだが、この講演の直前にこの原稿を書いたのが非常にラッキーで、知識の復習になってとてもよかった。

本当はこの中でJepsenの解説もしたかったのだが、他社製品をDisることになってしまうので自重。そしてこれの続編を書いているのだが、ハードコアすぎて終わりが見えない。3月号のつぎの4月号ではスピリチュアルな話ではなく、実際に手を動かしてRiakの整合性がどのように設計されているかについて解説する予定なので、3月号も4月号も買うとよいよ!!

なぜErlang/OTPなのか

このテーマ自体はさんざん語り尽くされていることである。たとえば山口君によるWhy Erlang? というブログ記事の翻訳や、戦闘機本(Programming Erlang: Software for a Concurrent World (Pragmatic Programmers))を読めば世間でいわれていることはよく分かる。もしくは、同僚が最近書いたソフトウェアデザインの記事を読んでもらってもよいだろう。

私自身もErlangに出会ってから5,6年が経とうとしているが、当初はそのよさがよくわかっていなかったように思う。しかし、仕事で高可用性が要求される複雑な分散システムに携わるようになって*1、いろいろな問題がコンピュータというか、データベースとか分散システムの世界にあることを知った。

メモリ管理の問題

単にmainを読んで、なんらかのロジックを実行してそれなりの時間で終了するプログラムを書いているうちは、メモリリークやメモリ管理の問題についてうるさくいうことはなかったのだけども、マルチスレッドでプログラムを動かしていて、開放されたところをうっかり他のスレッドがタイミング依存でさわってしまうとかいろいろあったわけで…
かといってメモリ管理をJavaやRubyのようなシステムでやってしまうとグローバルなGCをせざるを得ず、死活監視をほぼリアルタイム*2でやりたいといったときにGCでシステムが固まるのは困る。といったときにErlangの仕組みを考えてみると、Per-process-GCというのだけども、すべてのデータはTLSになっていてスレッド間のデータ渡しはメッセージなので基本的にはコピーで行う、というやり方をみて眼から鱗が落ちたのであった。メモリ管理に関する本質的な難しさが完全に解決するわけではないのだけども、人間の脳でもある程度考えられる程度になったという意味で、これと類似のことができるのはErlangくらいなものだと思う。

軽量プロセス

プログラミングモデルでいうと、1つのTCPコネクションに大して1つのOSプロセスをforkしたり、スレッドをcreateするのはとても自然なことである。そのTCPコネクションと、リクエスト処理に関わるもろもろのリソースのライフサイクルを一致させることができ、かつ、関係のない他のものと綺麗に分離できるためだ。だがちょっと待ってほしい。いくらCoWが働くとはいえ、ひとつのOSプロセスを起動して捨てるためのオーバーヘッドはいかほどのものだろうか。スレッドのスタックをある程度確保しないといけない。コンテキストスイッチも毎回おきる。レジスタは総入れ替えでキャッシュも効かなくなる(はず…)ので、モデルとしては正しくても、コスト的には釣り合わない。
そうするとどういうシステムになるかというと、たとえばクロージャを持ち回したり、TCPコネクションにひもづいたコンテキストの構造体を作ってスレッド間で引き回してスレッドプールを作って、つまらせたくない場合はキューをつくって別のスレッドプールに処理を流して、それのレスポンスをトリッキーな方法で待って…とやっていくと大抵は破綻するのである。一方でErlangの軽量プロセスとメッセージングの仕組みは、ひとつのTCPコネクションに対してひとつの軽量プロセスを割り当てる分かりやすいモデルにしつつ、ひとつの軽量プロセスのオーバーヘッドをかなり抑えることができる(300ワードくらいと言っていたような)。これを知ってしまうと、僕のようにあまり頭の回転がはやくないタイプはC++とかJavaで真面目に考えて実装するのはかなり面倒になってしまうのである。

Resilence

これを日本語でどういったらいいのかちょっと分からないが、耐久性というか安定性がある。ほっといても不安定になることはあまりないし、軽量プロセスを多少ぶっ壊したところで再起動するからどうってことないのである。もちろんErlang VM内部のメモリを破壊したらダメなところはあるのだが、それでもノンストップでコードをアップグレードしたりダウングレードできて、それが人間で扱えるレベルで簡単になっているのは恐ろしいことだ。ヤバい。鬼ヤバい。

マルチコア

20や30くらいのコア数だと安定してスケールする。GILとかGVLといったものがない。それは前述した通り、メモリ管理の方法が異なるためだ(もちろん、個々の軽量プロセスのレベルでGC時はとまってしまうのだが)。なので、ひとつのOSに複数のプロセスを起動する必要がない。それがChefがErlangを採用した理由だと聞いているが、何も考えずにOSプロセスをひとつ起動しておけばコアをよしなに使ってくれるのだから便利なものである。コア数が100や200まで増えたときの挙動はまだ私はよくしらないが、基本的にはN:Mのスレッドモデルをユーザー空間で実現しており、しかもメモリがShared-nothingなのでなんとかなるのではないかと楽観している。

まとめ

ここまでみてきたように、Erlangの言語そのものよりも、Erlang VMという処理系のメリットを私は気に入っているようだ。だから、Elixirのようなのものでも同じメリットを享受できる。安定したシステムを作るためにはErlangは最適の処理系である。

残念なところ

とはいっても、残念なところは沢山あるのでちょっと愚痴をいっておきたい。

まず、何よりも型安全ではない。この点ではRubyやPythonと同類で、うっかりテストを忘れていると修正で簡単にデグレがおきる。それを防ぐためのちょっと賢い方法としてDialyzerやQuickCheckがあるが、できればコンパイラと密結合してほしいものである。そのためには今のような beam ファイルの構成ではなくて、全ての実行ファイルを静的に結合してしまってひとつの実行ファイルにするのがよいのであるが、そうするとモジュール毎のライブアップデートや、ネットワークなど外部から変なTermが飛んできたときの扱いやらで、ずっと走り続けるシステムに静的で型安全な世界はムズカシイのかもしれない。それでも、Tupleじゃない代数的データ型、ほしいやん…

古い仕様が残っていることが多い。なるべく使わないものや有害なものはDeprecateしたり使えなくなるようになっているのだが、やはり長期間走るシステムをターゲットにしているだけあって古い仕様を捨てることはあまりない。まあこれはしょうがないか。

最後にDisclaimerであるが、この文章は読み返しているとはいえ、酔っ払って書いたものなのでどうか適度に聞き流して忘れてほしい。

ニッカ 余市 12年 45度 700ml

ニッカ 余市 12年 45度 700ml

*1:実装やテストの作業に携われなかったのは今でも口惜しい

*2:古典的な意味で

ひさしぶりに音楽をたくさん買った

新譜を追いかけるのも面倒になってしまって、ここ数年は電車の中でさえ音楽を全く聴いていなかったのだけども、ふと思い立って、自分のiTunesのライブラリをみながら新譜を出しているかどうか調べてみると案外たくさん出していたので、まとめ買いしたものを紹介。試聴すらしないで買うとか、忙しくなったものである。

COMEDOWN MACHINE

COMEDOWN MACHINE

なんといってもStrokesがいつの間にか出していたのは嬉しい。1曲目でブッ飛ばされた(痛)。

Bloodsports

Bloodsports

Suede復活して一枚出したのは知っていたけど、昔ながらの感じが復活してとてもよい。

RANDOM ACCESS MEMORIES

RANDOM ACCESS MEMORIES

これがグラミーをとったやつなのかな?歴代の曲を追えているわけではないけど、あいかわらずかっこいい。ぼくもこれくらいかっこよくなりたい。

Four

Four

ちょっと落ち着きが出てきたか?

Codes & Keys

Codes & Keys

まだ聴いてない。

Right Thoughts, Right Words, Right Action (LTD Edition Double Gatefold CD)

Right Thoughts, Right Words, Right Action (LTD Edition Double Gatefold CD)

まだ聴いてない。

さすがにThe MusicとかUnion of Knivesとかはもう出していなかったというか、彼らは帰ってこないのだろうな。いやNew Orderとかはもう帰ってこなくていいですよ思い出は思い出のままでいいよ…

それにしても、どうしてこのmp3全盛の時代にCDを買ったのかというと、こういった光学というかディスクのメディアに何がしかの郷愁がないかといわれたらウソになるのであるが、それだけではないように思える。どうしてだろうか。CDはまだ物理媒体だが、書籍はもう完全に電子書籍メインにすることにした(ただしフリーのPDFのみでKindleは使わない)。あの質量、体積の効率の悪さは子供がいる家庭では完全に邪魔でしかない。まだ電子書籍になれないところもあるが、私のように飛ばし読みして内容を忘れてあとで読み返しもしないような人間にはソレくらいがちょうどよいのだろう。
CDはまだ数が少ないし、書籍に比べると場所をとらない。それにもうiPhoneで持ち歩いているし、MacからRipしてiPodなりで持ち歩く生活はもう10年以上続けているのでまあ、オリジナルの媒体くらいは持っておこうかなとも思ったわけである。電子書籍やmp3で買った音楽と違って、やっぱりモノがあると買った気がするし記憶に残るので聴こうという気になるのである。不思議なものである。

筑波大学でデータベースの話をしてきました

f:id:kuenishi:20140201231755j:plain

筑波大学の川島先生に呼ばれて木、金と情報システム特別講義Dというやつに参加してきた。こんなことになるとは思っていなかったが、あろうことか講師側で呼ばれてしまい、思えば遠くへ来たものだと感慨深い。フリは「RiakとNoSQLの話をしてもらえたら」という非常に自由度の高い内容なので、せっかくなので僕の知っていることを全部詰め込んで話してやろうと思ったら10分延長してさらにスライド10枚分くらいを消化不良で終了という、みっともない感じになってしまった。かなり端折ってポイントだけ説明したので流れが分からず苦労した方も多いと思うが、まあ僕の性格なので許してほしい。データベースの講義をひと通り終えた院生レベルを想定してスライドを作ったので、もしかすると、わりと難しかったり分かりにくかったりするかもしれないので、わからないことがあったら適当に質問してください。

言いたかったことの流れを僕なりにまとめると

  • SQLが登場する前はみんなNoSQLデータベースだった
  • NoSQLのポイントは、スケーリングの問題、整合性、可用性が大きなみっつの問題
  • スケーリングは二通りの流儀がある
  • 整合性はアトミックブロードキャストプロトコルで頑張る
  • 整合性の話はふたつの文脈がある(トランザクションとレプリケーション)
  • 死活監視のデモでCrash Failure, Crash Recovery, Timing Failure, Silent Failureなどを体感
  • Paxosの説明に失敗
  • 可用性とCAP定理
  • ACIDとBASEは異なる概念なので混同どころか比較できない
  • データストアの分類 NoSQLではなくNoACIDがおもしろい
    • これはよい質問があってそのときはどう答えたのか覚えていないのだけど、今答えると、データベースは関係代数のデータモデルとトランザクション管理のふたつの部分から成っているのだけど、NoSQLは前者に対応するべきで、NoACID的なのは後者に対応すべき。なのだけど世間では混同されているのでここは注意した方がよい
  • それなりの分類軸のはなし
  • スキーマとかスキーマレスとか、ドキュメント指向とかカラム指向とか
    • 実は、ドキュメント指向DBはJSONだけでなくXMLもドキュメントとして扱うものがおおいのだけど、実はXMLは2階の正規モデルだかなんだか?になっていてふつうにSQLでクエリが書ける…という指摘をいただきまして、確かにドキュメント指向DBがアヤシいところのひとつではある。ただ、これは2000年代のデータベースのトレンドだったと記憶しているんだけど実は現実世界で役に立っているところをあまり見たことがない。
  • というところで、データベースを知る観点をひととおり説明して、Riakはこうしていますよという話をして終了。

整合性にはふたつの文脈がある話と、NoSQL/NoACIDの見方考え方はどうしてもぼくが伝えたかった話なので、昨今のNoSQL Buzzマーケティング*1に騙されないためにも必要で、それだけでも伝わってるとよいのであるが。

そのあと、全員の講義が終わったあとに佐藤さんと星野さんにCRDTのデモをちょろっとしてあとは終了。他の講義もとても濃く、こんな話を聞けるのは日本でここだけだなー、データベースの研究してる人沢山いるはずなのにおかしいなーと思った次第でありました。

この手の話、日本語の教科書などは当然あるはずもなく、まああえていうならGuide to Reliable Distributed Systems: Building High-Assurance Applications and Cloud-Hosted Services (Texts in Computer Science)がそれにあたるかなと思うのだけどまだちゃんと読んでないので、興味ある人はリスクを承知のうえで読んでみるとよいかもしれない。

筑波はとても距離的にも遠く、ネット上で元気なTKB勢をみてると遠い世界だなーと思っていたのだけどふつうの総合大学でキャピキャピしてる人も多かったし、おいしいレストランもあったしで正直TKB舐めてたのをとても見なおした。すいませんでした。

*1:ついに実用段階に入ったとか、Web Scale Databaseがどうたらとか、いろいろありますね

エンジニアCROSS 2014で登壇してきた

リピ君に声をかけられて分散処理システムCROSSというセッションに登壇してきた。立場としてはRiakという分散システムを商用製品として開発している人間…というわけだが、その前にはJubatusという分散システムを(一応)最初に設計して*1、他にもお仕事でいくつか設計したり開発してきた身。事前に打ち合わせと称して一度メンバーで飲んだときが盛り上がりのピークと思われ「裏番組すごいしどーせ誰も来ないだろせいぜい特定の5人だな」と話していたのだけども、蓋を開けてみると席が8割型埋まってしまうという盛況ぶり。で、途端に緊張し始めたわけで…

とりあえず、自分が多少ウザくても主張したいことをキーノートスライドに入れておいて「ネットワークはキレるんです」とか言っておいたのだけど、それを話したところで会場はポカーンとしてしまっていたので僕の話はそこまで。いちおうPaxosとかRaftについて知ってる範囲で話をしたのだけども、それでもポカーンとしてた…反省。いちおうQuickCheck (PULSE) とJepsenという名前を出せたしそれでよかったとする。ちなみに当のJepsenは作者が飽きてしまったらしく動かないところ(RedisやMongoとか)が多いので僕のforkをこの場でコッソリお勧めしておく。

まだまだHadoop人気は衰えていないらしく、会場の参加者は(Hadoopを筆頭とする)分散システムをガチで使っている人は少なく、これから使ってみたいけどどうやったら上手く運用できるかに興味があるようだった。なのでそういう方向に誘導してみたものの、まあ運用なんて仕組みが分かっていても分からない事象が起きて風が吹けば桶屋が儲かるみたいなことが多いのでアヤシいノードがいたら落とすなり外すなり早めにやりましょうところでEC2の故障モデルってどうなんですかねアマゾンさんニヤニヤみたいな展開になり、それまで饒舌だったショットさんが急にキリッとしてきたところで会場はいよいよシリアストークへ…となったところでタイムアップ。

やはり分散システムのテストと運用は鬼門ですねニヤニヤ、運用の話はまあ出尽くしている感があるので今度分散システムのテスト勉強会でもやりますかぁ〜ってことで後はビールタイムでした。

さてこのCROSSというイベント、首都圏のITコミュニティのキーパーソンが数多く集まっていたことで、このビルが突然地盤沈下でもしようものなら日本の著名なWebサービススマホアプリの半数が滅びるだろうというような楽しいイベントであった。いつもの面子が集まるだけでなく、各クラスタの「いつもの面子」が集まって交流するという素晴らしい趣旨を実践していて、また来年もあったら参加したいものだなあと思った。ちなみに2013年も登壇しないかと声をかけられていたものの、外せない海外出張があり断念していたのでありました…今年は参加できてよかった。

分散システムのテスト

これについては、Basho謹製の riak_test という結合テスト用のフレームワーク、QuickCheckによるプロパティテスト、PULSEによるRace Conditionテストくらいの話はできる(かもしれない)。あとはJepsenをもうちょっとメンテナンスすればそれなりによいものになると思うのだけど、なんせClojureで書かれているので私には勉強が必要…。

*1:機械学習のところはサッパリなのですが

ソフトウェアデザイン2月号はHadoopのはなしです

Riak CSは以前にも紹介したとおり、S3とほぼ同じAPIを持っているのでMapReduceに入っているjets3tがそのまま使えるので、HDFSの代わりにRiak CS使ってみようよという試みです。以前ぼくもHDFSにデータを出し入れしようとしたら結構たいへんだったので、Riak CSが使える場面もまあまああるかもしれない。一方でMapReduceは、分散処理においては他に選択肢がない。最近でこそいろいろ出てきたがやはり鉄板でして…

他に選択肢がないとは、どういうことかというと、自分たちの環境やユースケースに合わず多少使いにくくても我慢して使わなければならないということ *1。特にHDFSバッチ処理のための分散ファイルシステムとしては非常に優れており、高性能で安定していたが、ネームノードを特別扱いする運用が複雑になったり、ユーザー管理の仕組みがあとづけであったり、インターフェースが独自のものであったりと、通常のファイルシステムには、使いやすさは及ばない(当たり前なのだけど)。特に、比較的小さなファイルを大量に管理したい場合にはネームノードのメモリが不足しがちになる。これに対して、市場ではいくつかの分散ファイルシステムが登場した。GlusterFSはその筆頭でしょう。また、AmazonのS3もサービスであるが、これは技術的には分散ファイルシステムで構成される(と想像される)。実際にHadoopが必要な場面で、HDFSである必要がない場合もあります。HDFSが特に有効なのはI/O分散が可能だからで、I/Oインテンシブなワークロードに対して絶対的な優位性を今でも持っている。

実はMapReduceが動くのでHiveも動くと想像されるのだけど、Hive力が足りずなかなか手を動かせていない状態。黄色い象蜂が得意な人誰か試してみてくれないかなあ。

追記

同僚がErlang/OTPの入門記事を書いているので、そちらもどうぞ。まあ言語というよりは処理系の宣伝になってしまっていますが…

追記2: あわせて読みたい

Hadoop 第3版

Hadoop 第3版

*1:もちろん、自分が便利なようにパッチを送る、別のものを自分で作る等の選択肢はあ るし、Hadoopコミュニティは多様なニーズに適応しようと努力している。しかし、これではあまりに時間と手間がかかる場合がある

poolcatというライブラリを公開した

以前gen_queueというライブラリを公開したが、またライブラリ公開のお知らせだ。今回作ったのはpoolcatという、いかにもpoolboyからパクったような名前であるが、poolboyはネーミングの参考になった。

これも大したものではないのだが、ワーカープール+タスクキューのようなものをやるライブラリを見つけられず、どうも同じものを何度も再実装していたのでgen_queueを使ってライブラリ化してみたら思いの他便利で、同じレポジトリの3箇所で既存のコードを大幅に削ることができた。デバッグの手間も省けるというものだ。改めてOTPの勉強になったという…ちょっと調べた限りだとRabbitMQの中にも似たような機能があるし、Riak CSの中にもある。たしかRiakの中にも似たようなものを作ってるはずで…と、まあ再発明よくないですよね。という結論に。

poolboyじゃダメなん?

poolboyはコネクションプーリングなど、「使われる」リソースの側をリミットをつけつつプールしておくためのものなので、今回のように「使う」側にリミットをつけるのが目的なので、poolboyだとそれなりにワークアラウンドが必要になる(というか、どうやってやるんだ?)ので、まあどうせ小さなコードだろうし素振りも兼ねて作ってみたのである。

なぜタスクキューが必要なのか?

Erlangは軽量プロセスが売りなのであって、タスクを非同期に処理したければ軽量プロセスをspawnしておけばあとはrunqueueがよしなにスケジューリングしてくれる…と思っていた時期が私にもあった。実際にやってみると、Erlang VMのスケジューリングは(当たり前だが)まあまあフェアなので、例えば10万個のタスクを同時にspawnすると、起動した軽量プロセスの中身によっては例えば10万個のファイルディスクリプタやTCPコネクション、それなりのメモリを確保しようとプロセスが動くわけで(ちなみに一番困るのはエフェメラルポートを使われるケース)、トータルでの性能は劇的に下がってしまう。これを防ぐためにはいくつか方法があると思うのだけど、ちょろちょろっと試行錯誤した結果やはり伝統的なこのモデルが便利だなあということに今更ながら気づいたのであった。それじゃErlang使ってる意味ねーじゃん!というツッコミに関していうと、軽量プロセスはすごいものでたとえばConsumerになる軽量プロセスそのものは100万くらいになってもおそらくErlang VMそのものはビクともしないのでやっぱりいつか便利になる時がくるだろうと信じている。

アイディア自体はここ1週間くらいなのだけど、実装は子供の相手をしたりしなかったりしながら、土曜日の1日でできてしまった。こういうしょうもないライブラリを作るのとかは得意だし、それでも1日でできるようになったというのは腕が上がったなあとか、転職した甲斐があったものだと思う。これを使ってちょっとしたサービスを作ろうと思っているのだけど、さすがにまだ無理かなあ。

2014年になりました

この手の話は遡ってみると2012年の正月に書いたもの以来ということになるようだ。この2年何があったかというとまあ転職して仕事でErlang/OTPを書くようになったとか、転職して仕事の考え方が大きく変わった(正確にいえば、なんとなく感じていたものが確信と実践になった)くらい。
そういえば書き納めと書き初めはOCamlでした。みなさまに置かれましては昨年と変わらぬご愛顧のほどをいただければと思います。