In part 1 and part 2, I laid out my initial approaches on caching and performance in Cullect.
While both of them pointed in the right direction, I realized I was caching the wrong stuff in the wrong way.
Since then, I tried replicating the database – one db for writes, one for reads. Unfortunately, they got terribly out of sync just making things worse. I turned off the 2nd database and replaced it with another pack of mongrels (a much more satisfying use of the server anyway).
Cullect has 2 very database intensive processes: grabbing the items within a given reading list (of which calculating ‘importance’ is the most intensive) and parsing the feeds.
Both cause problems for the opposite reasons – the former is read and sort intensive while the latter is write intensive. Both can grind the website itself to a halt.
Over the last couple weeks, I moved all the intensive tasks to a queue processed by Delayed_Job and I’m caching the reading lists’ items in database table – rather than memcache.
Yes, this means every request is pulled from the cache, and a ‘update reading list’ job is put into the queue.
So far, this ‘stale while update’ approach is working far better than the previous approaches.
BTW, as this practice confirms, the easiest way to increase the performance of your Ruby-based app is to give your database more resources.