Google AppEngine Standard Environmentのpythonにはdatastoreのマッパーであるndbがとても便利で使いやすいです。
このライブラリは内部でキャッシングを行なってくれるため、平均取得時間の遅延を下げてくれます。
内部ではIn-Contextキャッシュとmemcacheを使ったキャッシュを併用しています。
datastore更新後もmemcacheにキャッシュが残る
memcacheを使わないコンテキストでの更新やGCEや外部からの更新時に、memcacheの更新を怠ってしまうとキャッシュの削除が行われずに、いつまでも更新後のデータが取得できなくなるケースがあります。
AppEngineからキャッシュをdisableにして保存
AppEngineから保存する時に、contextのポリシーでmemcacheへの同期をoffにして保存等してしまうと、キャッシュを利用している別のcontextと不整合が起きてしまいます。
from google.appengine.ext import ndb
class Item(ndb.Model):
name = ndb.StringProperty()
item = Item.get_by_id('item1')
item.name = 'car'
item.put() # 通常はmemcacheにも保存されます
# キャッシュを使いたくないケースで、memcacheをcontext内でオフにしてしまう
ctx = ndb.get_context()
ctx.set_memcache_policy(False)
item = Item.get_by_id('item1')
item.name = 'train'
item.put() # キャッシュポリシーがOFFだとmemcacheに保存されません
実際に、memcacheをオフにするケースはtaskqueue等で非同期で更新していたりするケースが多いと思いますが、時々遭遇してしまいます。
memcacheにアクセスできない環境から保存
GCEや外部など、memcacheにアクセスできない環境からdatastoreの更新や保存をした場合に、memcacheに保存されずに不整合が起きます。
google-cloud-pythonライブラリなどを使うことが多いと思いますが、その時に遭遇することが多いです。
# google-cloud-pythonを使った場合
from google.cloud import datastore
client = datastore.Client('my-project')
item = client.get(client.key('Item', 'item1'))
item['name'] = 'airplane'
client.put(item) # memcacheには保存されません。
(GCE上などからmemcacheの読み書きをする方法を知らないので、知っていたら教えてください。)
コンソール上で編集
コンソール上で編集する機能がありますが、これで編集してしまってもmemcacheには保存されない現象が起きてしまいます。
静的なconfig等をdatastoreで管理していて、それを更新した時に反映されない、といったケースに遭遇しました。
解決策
memcache全体をクリア(flash)すれば解決
memcache上に保存されているものを全て削除してしまえば、このような問題は解決します。
Memcacheのページからもフラッシュできます。
しかし、appengineからのdatastoreアクセスのパフォーマンスがその時に低下してしまうと思われるので、あまりやりたくないケースも多いですよね。
memcacheの該当データだけ削除
該当のデータだけmemcache上から削除すれば、そのデータだけが再取得されるので、全体のパフォーマンスへの影響を減らせるかと思います。
保存しているkeyを知って入れば良いのですが、ndb内部でmemcacheへ保存するときのkeyを決めています。
具体的にはprefix + entityのkeyのハッシュです。
prefixはndb.Context._memcache_prefix
に定義されていますが、appengine sdk 1.9.55ではNDB9:
となっていました。
なので以下のようにすれば削除できそうです。
item = Item.get_by_id('item1')
memcache.delete('{}{}'.format(ndb.Context._memcache_prefix, item.key.urlsafe()))
ndbライブラリ自体はappengineのpython sdkに含まれていて、github等で公開されていない?のでソースを見てみる必要があって少しわかりづらかったです。
中身もアップデートはあまりされていないみたいですし、先行きは少し不安ですね。