Webアプリをとりまく最近のKVS事情、雑感
RDBの復権はしばらくないと思う
最近目にしたのは、「これからRDBが十分速くなっていくので、memcachedに代わってRDBがまた使われるようになる」という意見。これはしばらくの間は無いんじゃないかと思う。全データがオンメモリだったとしても、KVSはRDBより一桁以上速い(Memcachedで100,000req/sec出せるマシンで、MySQLのpkeyによる単純なSELECTをした場合、10,000req/sec出るかどうか)。SQLパーサやらなんやらを捨てない限りこの速さには対抗できない。RDBには、1コネクション1スレッドというモデルが持つ、接続数がスケールしないという制約もある。
また、memcacheプロトコルは、get_multiが使える。get_multiを効果的に活用した場合、RDBとの差はさらに広がると思う。
RDBで大丈夫なアプリも
Viewキャッシュが効果的なアプリ(blogタイプ)と、そうでないアプリ(SNSタイプ)で、RDBの遅さを許容できるかどうかが左右される。ちなみにLang-8は後者。以下後者のタイプを前提に話を進めます。
KVSなクラウドDBは?
GAEのBigtable, AmazonのSimpleDBあたりが利用できるけれども、レイテンシがかなり大きいとか。一クエリ10msとか普通にかかるらしく、これは許容しがたい。。当分はクラウド利用を諦めて、手元でサーバをセットアップして使うしかないのか。。
レンジクエリ?
KVS上でレンジクエリは利用できるのか? いろいろアイデアがあるようだが、今すぐにプロダクトへ採用できる状況ではなさそう。クエリの制約も大きく、SQLを代替できるものではない。
レンジクエリが使えない場合、インデックス構造自体をKVS上の1レコードとして持つ必要がある。これで案外いける。各レコードへの参照を並べるだけのListなので、アプリ側で適切に分割した場合、レコードサイズが1MB(Memcachedの制約)を超えることはまずない(例:Lang-8のフレンドリストや、個人ごとの最新日記リスト)
1MB以上になりそうな場合は、レコード末尾に続きのインデックスへの参照を置き、数珠つなぎに引っ張り出す等、アプリ側で工夫する。(泥臭い。。)
排他ロック
KVSをメインストレージに採用する場合、書き込みの競合によるデータ欠損を防ぐため、レコード単位でのmutexが必要。拙作KVS支援ライブラリ、SimpleResourceでは、ライブラリ側の機能として提供した。
スキーマレス
スキーマレスが普通になっていく。スキーマレスのメリットは非常に大きい。SimpleResourceや、SimpleResource上で再構築したLang-8でも、すべてのレコードはスキーマレスにした。
RDBが部分的に補助
どうしてもKVSでは処理できない検索クエリだけRDBで処理するというスタイル。RDB上のデータはただのインデックスという位置づけであり、マスタデータではない。Lang-8の場合は任意のパラメータによる日記・プロフィール検索等でこのスタイルを使っている
トランザクション?
諦める。関連する複数のレコードのうち一部だけ書き換えられても破綻しないように、アプリ側で工夫する。