高速化のためにRDBをやめてみるテスト。

http://blog.masuidrive.jp/index.php/2008/09/23/concurrency-on-the-web/

わかります。

 これでは、写真をアップすることに100人分のXMLを生成する事になります。

この手の問題は悩まされます。ちょっと話がずれるかもしれませんが、ある程度の解決の方向性が見えているかな?、と注目しているのが、CouchDBのView方式。

CouchDBの場合だと、HTTPで放り込んだデータそのものは、すぐにディスクに'''追記'''されますが、そのデータをView経由(=加工して)で取り出す場合には、初めてアクセスがあった場合に'''前回のアクセスから追記された部分を対象に再度Viewを作成する(=加工したスナップショットを作る)'''処理が走るようになります。

例えば。

# client1 は client 3 をフォローする, client2 はclient3をフォローしない
client1 == (GET /client1/followings ) ==> Apache (mox_proxy) ==> CouchDB View1  ...(*1)
client2 == (GET /client2/followings ) ==> Apache (mox_proxy) ==> CouchDB View2  

# 新しいデータを追加する場合(写真の投稿)、
client3 == (POST /client3/photos) ==> Apache => Rails == (HTTP POST) ==> CouchDB... (*2)

# ユーザーたちのアクセス 
if (client == client1)
   client1 == (GET /client1/followings ) ==> Apache (mox_proxy) ==> CouchDB View1 ... (*3)
else
   client2 == (GET /client1/followings ) ==> Apache (mox_proxy) ==> CouchDB View2 ... (*4)
end

(*1) では、すでにあるView(btreeでかかれたファイル)を返します。これはキャッシュ(といってもいいぐらいのもの)です。

(*2) では、キャッシュの元になっているオリジナルのDBファイルにデータが追記されるだけで、キャッシュは更新されません。レスポンス性能は momochiweb と couchdb_btree.erl 次第、といったところですがそれなりに期待できると思います。

で、(*2) => (*3) のパスを通る場合にはじめて、View1(キャッシュ)の更新(MapReduceで実装したJavaScript)が行われます。一から作り直すわけではなく、更新のあったファイルを対象に処理が行われます。View1はclient3のデータを元に作られているからです。こんなにうまくいくかどうかはMapReduceの実装次第。

(*2) => (*4)のパスを通る場合は何も起こりません。

ユーザーを待たせたくないのであれば、cronか何かで、CouchDBのViewを一定感覚でリクエストしておけばよさそうです(コメントにも同じような考え方のがありますね)。

ただ、現時点のCouchDBの実装だと、アクセス制御とかできないし、そもそもJSONしか返さないので、mod_proxyだけじゃ役不足かもしれません。mod を別途作るかApplication Server(RailsとかRack, mod_rubyとか)経由にしないと用件を満たせない可能性はあります。あと、CouchDBは更新も新規作成も全部データを追記するので、PostgreSQLのバキュームと同じように運用方法の検討も必要ですね。

この辺りのCouchDBの可能性、自分でも試したいんだけれど、なかなか時間がとれないので、考えを整理しながら記録だけしてみた。

あと、ブクマにあるようなJavaっていう選択肢の場合に、JRuby on Railsとかどうなんだろう、というのが興味津々。