This week I, with help from many, got [WordPressMU][wordpress] setup to use [memcached][memcached].
The instructions for doing all this are on the Internet, but I thought it might help others (or at least my future self) to compile them all in one spot.
### How WordPress caches
There are two layers of caching in WordPress:
* An object level cache, similar to Django’s [low-level cache][django-cache]
* Page level caching, provided by plugins, similar to Django’s [per-view cache][django-page-cache]
By the time we’re done, we’ll have both using memcache. The object cache defaults to the file system, and most folks use [WP Super Cache][super-cache] which caches pages to the filesystem as well.
### Object caching
* Install the [PHP memcache module][php-memcache]
* Add these settings to your **wp-config.php**
global $memcached_servers;
$memcached_servers = array('default' => array('127.0.0.1:11211'));
You can add as many servers and change the port number to match your memcached setup. Example:
global $memcached_servers;
$memcached_servers = array('default' => array('bradfitzrocks:11211', 'bradfitzrocks2.mycompanydomain.com:90210'));
* Install the memcache version of WordPress’s [object-cache.php][wp-object-cache] to your blog’s wp-content folder.
I don’t want to sidetrack myself comparing how much [Django][django] rocks compared to PHP or WordPress, but I will anyway! In Django, your cache setup is a [setting][cache-setting], which makes local development soooo much easier.
Stop here and you’ll be live with WordPress object caching.
### Page caching
* You must have followed the steps above to hook up WordPress’s object cache to memcache.
* If it’s installed, uninstall [WP Super Cache][super-cache]
* Install [Batcache][batcache-github] by putting advanced-cache.php file in your blog’s wp-content folder, and batcache.php in your blog’s wp-content/plugins folder.
* Activate the Batcache plugin from within the admin interface, if you’re on WordPressMU use the “Activate X Site Wide” link.
* Hit reload on a page a few times and then view source and you should see something like this:
<!--
generated 12 seconds ago
generated in 0.683 seconds
served from batcache in 0.006 seconds
expires in 288 seconds
-->
</head>
* Optionally, tweak Batcache’s behavior by editing the options in advanced-cache.php
var $max_age = 300; // Expire batcache items aged this many seconds (zero to disable batcache)
var $remote = 0; // Zero disables sending buffers to remote datacenters (req/sec is never sent)
var $times = 2; // Only batcache a page after it is accessed this many times... (two or more)
var $seconds = 120; // ...in this many seconds (zero to ignore this and use batcache immediately)
var $group = 'batcache'; // Name of memcached group. You can simulate a cache flush by changing this.
var $unique = array(); // If you conditionally serve different content, put the variable values here.
var $headers = array(); // Add headers here. These will be sent with every response from the cache.
var $uncached_headers = array('transfer-encoding'); // These headers will never be cached. Apply strtolower.
var $debug = true; // Set false to hide the batcache info <!-- comment -->
var $cache_control = true; // Set false to disable Last-Modified and Cache-Control headers
var $cancel = false; // Change this to cancel the output buffer. Use batcache_cancel();
The Batcache version I linked to is a GitHub fork of [Andy Skelton’s](http://github.com/skeltoac/batcache) original version. My fork includes a patch to make sure the Content-Type header is set correctly on non-HTML pages. I’m hoping to add some more cache invalidation rules on top of the great work Andy already did.
Many thanks to the following folks:
* [Mohanjith](http://mohanjith.net/blog/2008/10/using-memcached-with-wordpress-object-cache.html) for the object cache set up
* [Andy Skelton](http://skeltoac.com/) for creating Batcache and being kind enough to drop a version on GitHub for me to fork
* [Casey Bisson](http://maisonbisson.com/blog/post/13773/fixing-batcache-to-send-the-correct-content-type-header/) for describing the content-type patch for Batcache
[wordpress]: http://mu.wordpress.org/
[memcached]: http://www.danga.com/memcached/
[django-cache]: http://docs.djangoproject.com/en/dev/topics/cache/#the-low-level-cache-api
[django-page-cache]: http://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache
[django]: http://djangoproject.com
[super-cache]: http://wordpress.org/extend/plugins/wp-super-cache/
[php-memcache]: http://us.php.net/memcache
[wp-object-cache]: http://plugins.trac.wordpress.org/export/71058/memcached/trunk/object-cache.php
[cache-setting]: http://docs.djangoproject.com/en/dev/ref/settings/#cache-backend
[batcache-github]: http://github.com/cmheisel/batcache