M/SからHRDへの変更した場合、設計は変える必要があるのか?
appengine office hoursで、松尾殿にDatastoreの2つの形式は今後どうなるのか聞いてみた。
「これからのDatastoreの主流はHRDとなり、いずれ、M/Sは使えなくなるだろう。」
既にPython2.7はHRD限定だし、javaでも新規AppはHRDだ。
M/Sも最低数年はサポートするが、いずれ無くなる可能性があるとのことだった。
僕が作成中のAppはM/Sのままだったので、Appを一度削除し、作りなおした。
しかし、ここで疑問が沸く。
HRDにしたのは良いが、実装はどう変えれば良いの?
そんなことを考えながら調べていたら、以下の話を見つけた。
put直後にqueryで取得しようとすると、Indexが更新されてなくて、
意図したデータが取れないことがあるよ!
ということだろう。
そして、それを考慮した設計が必要であると・・・!
が、しかし!!!
それを考慮した設計というのが、具体的にどのようにすることなのか分からない!
ということで、もう一回appengine office hoursで、松尾殿に聞いてみた!
まず、Indexの更新にかかる時間だが、99%は数十msで更新。残りの1%は遅くて2sぐらいらしい。
強い結果整合性を求めない限りは、そういうものですとユーザに伝える程度でも大丈夫。
しかし、強い結果整合性が欲しい!という場合は、以下のような対処の方法がある。
1.Keyによるgetに切り替える。
とても単純。
2.ancestor query を使う。
ancestor queryは強い結果整合性を持つ。
マルチユーザのブログの場合、各ユーザに親Entityを作成し、記事をそれの子Entityとする。
しかし、その記事にコメントを付ける場合は、同じ設計にするかは考える必要がある。
コメントは不特定多数のユーザが書き込むため、datastore contention が発生しやすくなる。
これかな?http://code.google.com/intl/ja/appengine/docs/java/datastore/hr/overview.html
3.クエリの結果を、再度検証する。
銀行口座で、100円以上口座に預けているデータをqueryで取得する場合。
ユーザAの口座にはある時点で、120円あったが、30円引き出し、90円となった。
もし、Index更新前にqueryを実行した場合、ユーザAの口座も取得してしまうかもしれない。
そのため、取得後に再度データを検証する。(ループで回して100円未満の口座をはじくなど)
教えていただいたのは、この3つ。
特に3の話を聞いた時に、
最新のデータが取れないわけではなく、Indexが更新されていないことがある。
の意味が分かった。
口座に100円以上あるという条件で、90円のデータが取れてしまうのだ。
しかし、120円の時点のデータが取れてしまうわけではない。
データは90円に更新されているが、Indexが120円のままなのだ。
HRDにしたからと言って、物凄く神経質になることは無いということが分かったので、安心した。