Key based cache invalidation example

Hi, I just read your blog post titled Last Mile Redis. In the article a key-based cache invalidation scheme is described. I checked the link (https://archive.is/CDaVX) but I’m still missing something about how using this scheme would ensure that reading stale data is not possible. I’m not familiar with Rails and I haven’t been able to find an example of how this technique works elsewhere on the web. Could somebody describe how this technique works or post a link to such information? Thanks

The key based cache invalidation won’t completely prevent reading stale data, it just simplifies the problem of expiring dependent caches.

Here’s an article about doing it with Django: Key-based cache expiration with Django - Ross Poulton

The general idea is that generate create cache keys using a version (which could be a timestamp, like updated_at). When you cache a record from a database, like a user, you use a key like user/<id>/<version>.

The problem with this is that you need to keep current version of everything available to your code. You can do some of this by changing updated_at for a whole tree of records. For example, if you have users and groups, you’d touch the updated_at column on all groups a user belongs to when that user changes.

To render a bunch of groups, you’d do something like:

users = query("SELECT id, name, updated_at FROM groups")
for(g in groups){
  key = ["group", g.id, g.updated_at].join("/")
  cached = cache.get(key)
  if(!cached){
    cached = render(g) // this presumably uses cached `user/*` values
    cache.set(key, cached)
  }
  return cached
}

This is not the easiest thing to model, but it’s simpler than doing reliable cache purging for many kinds of applications.

Does that help?

Yeah that helps a lot thanks. The comments on the original article were also useful for anybody reading up on this. I missed them the first time around. How key-based cache expiration works – Signal v. Noise

1 Like