Improving WordPress Caching: Batcache and Redirects

BatmanThere’s a great plugin for WordPress called Batcache by Andy Skelton, which uses memcached as the cache backend for object cache and full page caches. It’s a great piece of code, and using it is a must if you want a scalable distributed cache for your WordPress install (avoiding the local file system caching WP-Super-Cache offers).

I’ve been running batcache for a while, and noticed that although I set up a query-heavy homepage to be cached for a long while, the homepage query was still running every couple of minutes. So after some digging and logging I came to realize that batcache was missing an important part — caching redirects.

Why is it important to cache redirects? Here’s an example. If I go to http://example.com/, my homepage will be cached. But when I go to http://www.example.com/, the homepage query still runs. This is because the default www to no-www redirect happens at ‘template-redirect’ action time (with canonical_redirect()), which occurs after the main posts query is run. And, batcache wouldn’t cache the redirect itself nor would it associate the www with the no-www version (it differentiates pages by a couple of parameters, including HTTP_HOST, which is different in this case). So any request to http://www.example.com would actually first run the homepage query, then redirect to http://example.com and serve the cached version only then.

After a short correspondence with Andy, he committed a changeset to advanced-cache.php (and readme.txt ;) ) that now enables to cache redirects (off by default, be sure to turn it on!). Great to see such responsiveness from a plugin author, and I hope it helps others as well.

Memcached Storage Class for Zend_OpenId_Provider

I experimented a bit with creating an OpenID provider entity using Zend_OpenId_Provider. It was not a hard task to implement, but seeing that the default storage class is file based made me shiver. There are two reasons why I hate anything to do with local disk access:

  • It’s s-l-o-w-w-w. Disk I/O is the pitfall of performance for web applications. Avoid when possible.
  • It’s usually not fitting for clustered environments. If you have a cluster of application servers (running php for example), and you are using disk access, it will only update the disk on the application node you were directed to in the current request. On the next request to the application, you might not be directed to the same application server (if the load balancing is not ip-hashed or session based). Of course this is not always the case – sometimes there’s a network storage, sometimes several directories can be rsynced across the cluster — but as a rule of thumb, local disk access is not good for clustered environments.

So the obvious thing when implementing an OpenID provider using Zend Framework is to change the default Storage class, and use a storage that’s not a traditional filesystem. Before jumping into using a MySQL backend for this, and coming up with a full blown OpenID provider, I needed something quick that will replace disk storage, but will also work on a clustered environment. So it was really natural to turn to memcached.

I am not sure that using memcached as a final storage engine for an OpenID provider is really a good call. Caches expire, keys are being purged, and whole memcached nodes can evaporate. However, it might fit a provider that is not a full blown OpenID service. If you can find a way to addUser() to the storage every time before a user starts an authentication attempt (and it’s not that difficult, considering the 10-stage authentication process), and if you can handle associations and other info being deleted from time to time (and if your users can handle it…) — memcached storage can be what you need.

In any case, even if just for testing purposes, here’s a memcached storage class for Zend Framework’s OpenID Provider I wrote (it’s a plain text file, apologies for the doc/msword file type).