スティルハウスの書庫の書庫

はてなダイアリーで書いてた「スティルハウスの書庫」を移転してきました。

App Engineは「ACID保証しない」ではなく「ACID保証したくなくなる」

App Engine未体験の方の中には、「App Engineはトランザクションをサポートしていない」ような印象を持っている方もいるかもしれませんが、そんなことはありません。App Engineのドキュメントに

The App Engine datastore is strongly consistent, but it's not a relational database.

とあるように、エンティティグループ(EG)という限られた範囲ではACID特性を保証しています。

しかし、このEGが使いにくい。

  • 1つのEGにトランザクションが集中するとリトライが多発するので、個々のEGを小さくに負荷が集中しないように設計しなければならない
    • 例えばUserとそのAdressとか、子が少なくなるよう負荷が集中しないような使い方にする
    • 異なるEG間で整合性確保するには作り込みが必要
  • すると必然的に1つのロジックで2〜3のEGを扱うことになる
  • すると1つのロジックで複数のトランザクションを書くことになる。それぞれにtry/catch/commit/rollbackを書く
  • optimistic lockだから必要に応じてリトライも書く
  • しかもコーディングしていると間違って複数EGをさわってしまい、「java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction.」がよく出る。直す。コードが増える。
  • グローバルなカウンターとか、特定のEGに入れるのが難しい(でも入れないと数がずれそうな)ケースがよくある
  • 性能上げるためにDatastoreとmemcacheを絡めて使うけど、memcacheはトランザクショナルじゃない(ここでEntity BeanとかJMSのキューはインメモリかつトランザクショナルで便利だったな〜と懐かしむ)

...などとやっていると、「まあこの部分は、こんなにぐちゃぐちゃコード書いてまでムリしてトランザクショナルにしなくてもいいかな〜〜」と妥協したくなります。さらにjdoconfig.xmlに「 」などと書くとすごくラクになれます(麻薬)。

というわけで、App Engineでは正直ACID保証がめんどくさいです。これもクラウドではよくあることってことでしょうか。