CouchDB Compatible API Service on GAE

元々の目的は、データモデルがいい加減だとスケールする環境でもスケールしなくなるよ!という話のつもりだったんですが。ソースコードを公開しつつチャレンジしていこうと思います。

http://github.com/yssk22/gaecouch

今できることは README.md に書いてあるとおりで、データベース操作とドキュメント操作が行えます。

データモデルについて。

データベース全体を表現するために(CouchDBでは1ファイル)、Database(db.Model) というクラスを定義しています。これは簡単ですね。

次に、データベースに放り込むドキュメントを表現するために、Document(db.Model) というクラスを定義します。

しかしここで問題が。Document は id で一意に特定できるのはインターフェース上であって、内部的には _id と _rev の組み合わせが一意キーとなります。 そして、_id ごとに 1-XXX, 2-YYY, 3-ZZZ, ... というリビジョングループを持つので、_rev に関してはCAS操作が必要になります。

ということで、DocumentRoot(db.Model) というコントロール用モデルを作って、このモデルの中で最新のドキュメントへのポインタを保持するようにしました。そして、_idごとに DocumentRoot と Document をエンティティグループとしてまとめてあげれば、CAS操作のトランザクションもある程度のスケーラビリティが担保できるんじゃないかなぁ、

ところでGAEのマニュアルによれば、エンティティグループはおなじデータノードに保持します、とありますから、これって結局、_id で分散している、ってことですよね。

ここで犠牲になったのは、Database の update_seq, doc_count, doc_del_count。 まぁこれは、Eventual Consistency ということで、担保できればいいのかな、とか。

最終的な答え合わせはCouchDBソースコードを見ながらやろうとは思いますが、とりあえず振る舞いだけを手がかりに、CouchDBを他のスケールするといわれているシステム上で実装しようとすると、いろんな考察ができておもしろいですね。

ちなみに、まだ全然実装していないので、実装されていないAPIを呼び出すと HTTP 501 NotImplemented が返ってきます。

imac:gaecouch yssk22$ curl -v -X GET http://gaecouch.appspot.com/_stats
...
< HTTP/1.1 501 Not Implemented
< Cache-Control: no-cache
< Content-Type: text/plain; charset=utf-8
< Expires: Fri, 01 Jan 1990 00:00:00 GMT
< Date: Sun, 23 May 2010 10:56:58 GMT
< Server: Google Frontend
< Transfer-Encoding: chunked
< 
{"reason": "please contribute implementation.", "error": "not_implemented"}