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間で整合性確保するには作り込みが必要
- 例えばUserとそのAdressとか、
- すると必然的に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保証がめんどくさいです。これもクラウドではよくあることってことでしょうか。