Where is the best place to put cache-evicting logic in an AppEngine application?



I've written an application for Google AppEngine, and I'd like to make use of the memcache API to cut down on per-request CPU time. I've profiled the application and found that a large chunk of the CPU time is in template rendering and API calls to the datastore, and after chatting with a co-worker I jumped (perhaps a bit early?) to the conclusion that caching a chunk of a page's rendered HTML would cut down on the CPU time per request significantly. The caching pattern is pretty clean, but the question of where to put this logic of caching and evicting is a bit of a mystery to me.

For example, imagine an application's main page has an Announcements section. This section would need to be re-rendered after:

  • first read for anyone in the account,
  • a new announcement being added, and
  • an old announcement being deleted

Some options of where to put the evict_announcements_section_from_cache() method call:

  • in the Announcement Model's .delete(), and .put() methods
  • in the RequestHandler's .post() method
  • anywhere else?

Then in the RequestHandler's get page, I could potentially call get_announcements_section() which would follow the standard memcache pattern (check cache, add to cache on miss, return value) and pass that HTML down to the template for that chunk of the page.

Is it the typical design pattern to put the cache-evicting logic in the Model, or the Controller/RequestHandler, or somewhere else? Ideally I'd like to avoid having evicting logic with tentacles all over the code.

2 ответов


A couple of alternatives to regular eviction:

  1. The obvious one: Don't evict, and set a timer instead. Even a really short one - a few seconds - can cut down on effort a huge amount for a popular app, without users even noticing data may be a few seconds stale.
  2. Instead of evicting, generate the cache key based on criteria that change when the data does. For example, if retrieving the key of the most recent announcement is cheap, you could use that as part of the key of the cached data. When a new announcement is posted, you go looking for a key that doesn't exist, and create a new one as a result.

У меня есть такой декоратор в проекте Github с открытым исходным кодом:


Он немного более подробный, позволяя такие вещи, как принудительное выполнение функции (когда вы хотите обновить кеш) или принудительное локальное кеширование ... это были те вещи, которые мне нужны в моем приложении, поэтому я запек их в мой декоратор Memoize.