KVSというかNoSQL
前回までのあらすじ (1 2 3 4)
なんかあれ以降も週に一回くらい考えるのが習慣になってしまってるが…
一貫性云々とか言ってるのは↓こう、こういうことが言いたかったんですよ…多分…後付けだけど…
http://japan.cnet.com/blog/kenn/2010/09/20/entry_27042323/
「NoSQL」と言われてるけど、これは「クエリがリッチかどうか」「一貫性の問題にどう対応してるか」というふたつの軸に分けるべきだと思うのだよな。
すなわち、
- SQL → クエリがリッチ、一貫性の制約が強い
- NoSQL → 単一クエリのみ、一貫性の制約が弱い
と、なってるけど、「クエリがリッチで一貫性が弱い」という組み合わせが存在していてもよいと思う。「単一クエリのみで一貫性が強い」という組み合わせは必要かどうかわからんけど…
この区別を実現するためには、どのようなAPIがよいか?
クエリのリッチさは、インターフェースを変えなくてもバックエンドの最適化で対応可能であると思う。APIはSQLで統一して、シンプルなクエリが多数投げられる場合は、それに合わせたデータ構造にする、とかは可能だろう。
一方、一貫性の問題は、バックエンドで最適化することは不可能なのではないかと思う。マシンの電源が落ちたときに消えてもよいデータは何で、消えてもよくないデータは何か?というのは、アプリケーションが指定しないと、バックエンドが推測することは不可能だろう。推測した結果が間違っていれば一大事だ。
つまり、インターフェースで考慮しなければならない点は、「いかにして可視性/一貫性をアプリケーションから指定するか?」という点であると思う。
Memcached(やその他KVS)は、「単一のクエリで十分なアプリケーションでは、ほとんど一貫性は要求されない」という前提があったから、強力にスケールするキャッシュシステムが構築できた、と、考えるべきではないだろうか?つまり、重要だったのは、メモリにキャッシュされるとか、クエリがシンプルだったとかではなくて、「機能を弱めれば利用シーンが限定できる」という文化的な問題だったと見るべきでは?
僕が前々回まで「気持ち悪い」と書いてたのは、これで大分説明できる気がしている。すなわち、「世間一般ではMemcachedは、オンメモリとかシンプルなクエリとか書いてあるけど、一番本質的な部分は可視性/一貫性の問題ではないだろうか?」という思い。
この微妙なすれ違いは、実際に問題を起こしていると思う。例えば、TokyoCabinetとかは、プロセスが死んだ時の挙動について、苦情があるみたいなのだが(http://togetter.com/li/2282)、これは、最適化の一部が一貫性の維持を諦めていることによって実現されている、という点について説明がない、というかそもそも一貫性/可視性について仕様が決まっていないことが根本の原因であると思う。
と、いうわけで、一貫性/可視性について、きちんと定義されてあれば、SQLぐらいリッチでしかもスケールするストレージシステムは可能なんではないかと思う。(クエリが十分に最適化してある場合に限るけど)
- クエリごとに、一貫性/可視性を指定する仕組みをつくる
- 可視性は以下の四つ?
- 別に見えなくてもいい
- プロセス内で見えることを保証する(プライベートメモリ)
- OS内のプロセス間で見えることを保証する(共有メモリ)
- 電源断後も見えることを保証する(ディスク)
- 一貫性は
- どうでもいい、途中で書き込まれてそれが見えても別にいい
- 途中で書かれたら失敗する(トランザクション的な何か)
- 途中で書くのを許さない(ロック的な何か)
- 指定方法は、メモリみたいなのを
- read/write ともに、ロック/トランザクション的なインターフェースを用意
- writeに非同期なインターフェースを用意。waitのほうに、可視性についてのパラメータを渡す
- 順序づけるインターフェースを入れる
- 可視性は以下の四つ?
これで、クエリがどうであっても、複数サーバで書き込みをバッファリングする場合も、読み書きを完全に順序づける場合も対応できるのではないかと思う?
ほんまか?ソフトウェアの歴史的に、「99%の場合うまくいく複雑なインターフェース」は「90%の場合うまくいく簡単なインターフェース」に駆逐され続けてきたと言えて、僕の考えでは妄想世界の中ですでに「非同期でかつ一貫性を指定する」みたいなインターフェースはどうやってもシンプルになりえないので、まあ、多分無理だな。多分、現実的にはシンプルなインターフェースで、多少の問題には目をつぶるか、現場で対応みたいな感じになるんだろうな…という気がする。
このあたりは、色々と実験したいのだが、今は他にやることがあるのと、SQLとか系は全然やったことがないので机上の空論すぎるので、まあ、やるとしたら、一年後くらいに、SQL修行の旅に出て、それから、という感じかな、という気がする。
と、いうのを考えているのだが、「最近他人のSQL直してばっかりだ」と愚痴っていたF君に「実際SQLて何がボトルネックなん?」と聞いたら、「テーブル設計が糞なのがボトルネック」とのことでした。バックエンド関係無いのが現実である。