Topic: Strategy for intelligent cache keys on dynamic sites

I have a site that features schedules of TV shows, where registered users get to create custom ones via saved lists of shows and share them with friends. I've begun to implement fragment caching at the view level, and my cache keys are a mix of a unique string for the part of the site a block is on, the date where applicable (for things that change daily) and for users that are logged in, their username on the site, so that their personal schedule for shows they're interested on is cached e.g.. That's all been working well.

Now certain events (like a start/end date change or a new show being saved to a user's list) may take place that necessitate expiring these day long caches right away. In cases where the user isn't the one making the changes, they need to be expired by all users. Since memcached (which I'm using in Rails 3 via the dalli gem) can't do expirations based on wildcard in the cache key, I'm using a workaround where I storing a few namespace keys (for different parts of the site that might be outdated) and increment it to trigger expiring the cache, since this key is also part of my cache keys.

On to my actual point: Sometimes events may happen that only require a subset of user's caches to be expired. Moving the start date forward on a show so that it now appears in a personalized list of upcoming shows should only clear the cache for those users that are tracking that show. This means that I need to track each namespace on a per user basis, rather than one per part of the page that gets cached. Otherwise all I could do is say 'Well, a show got moved to within 30 days from today. Clear everyone's cache, since some might be tracking it'.

How to do this user based namespacing isn't really the problem. I'm more concerned about efficiency in the long run. Let's say a popular show is tracked by several hundred or even thousand users. If I'm doing per user expirations, I'm making a query against the DB for all those users, and then one memcached increment call for each of their personal namespaces. Although, those actions that necessitate expirations across multiple users won't be the result of a user initiated action, they'd be the result of a content admin who changes some data points on the backend, so a slight delay in the page response can be forgiven here. If it ends up taking too long, I can start farming this out to an asynchronous thread.

Hopefully this all made sense. Am I slicing my cache too thin here? Only user specific blocks will get this treatment of course. Other parts of the site Is this a viable and commonly used caching strategy?

Re: Strategy for intelligent cache keys on dynamic sites

I think the ultimate answer here is "it depends," as ambiguous as that is.

I've seen (and used) similar strategies to the one you described here.  If you slice your caching that thinly then you're essentially using memcache as a lightweight primary database that can be rebuilt from a secondary database, which is totally fine if you've got enough iron behind the scenes to perform those bulk updates.

I'm Chris Chandler, a Phoenix Ruby on Rails developer and startup junkie kicking ass at Flatterline, a Ruby on Rails web application development company.