-
Notifications
You must be signed in to change notification settings - Fork 3
Home
主旨としては、Datastoreに対する操作するとお金がえらいかかるのでMemcacheに可能な限り仕事させたいというお話。
現状、普通にプログラム書くとすると、プログラマが以下のような処理を記述する場合がほとんど。
- Datastoreにデータを読出 and 保存を行いたい。
- Memcacheからデータを読む。
- Memcacheからデータが取れなかった場合、Datastoreからデータを取ってくる。
- データを更新する。
- Datastoreに保存する。
- Memcacheに保存する。
これに、Delegateを噛ませてDatastoreのPut&Get時にMemcacheへの操作を同期的に行い、結果を差し替える。 全てのPutに対して適切に処理をすると、古いEntityを返してしまう心配はない。 Tx有りのGetの場合はMemcache無しで素通ししなければならない。
MemcacheのKey = EntityのKey
Entityごとガッツリ持ってくるQueryについて、KeysOnlyに書き換えてQueryを実行。 取得できたKey群について、個別にMemcacheからEntityを取得する。取得できなかった分はまとめてBatchGetする。
MemcacheのKey = EntityのKey
全ての種類のQueryについて、レスポンスをまるごとMemcacheに保存し活用する。 EntityがPutされた場合にQueryのキャッシュを破棄しなければならない。しかし、Memcacheから器用に特定のKindに関連したQueryのキャッシュを消すのは難しい。そのため、Kind単位にカウンタを持ち、MemcacheのKeyの生成にそのカウンタを利用する。もし、該当のKindのEntityがPutされた場合、カウンタの値をインクリメントする。結果、そのKindのQueryのキャッシュは参照できなくなり、上手く動くようになる。
MemcacheのKey = Namespace + @ + Kind + @ + クエリのハッシュ値 + カウンタの値
もし、Foo Kindのカウンタが3で、Namespace=FizzのQueryを投げると Fizz@Foo@123abc@3
のような値になる。
もし、Foo Kindに対してPutがあった場合、カウンタは4になりMemcacheのKeyが Fizz@Foo@123abc@4
のようになる。
これにより、古いキャッシュは参照されないようにすることができる。
問題点として、QueryがEventualなため最新ではないQueryResultをキャッシュしてしまった時に困る(Entityは最新しか取れない)。