Redis-Backed Page Caching for WordPress

We’ve been testing our new Redis-based page caching plugin for WordPress these past few months, and today we’re happy to announce that we’ve open sourced it and deployed to all customer nodes here on Pressjitsu.

Our MySQL-based caching solution has worked really well for our customers so far, but we thought we could use the same ideas and take them even further with Redis — an extremely fast and flexible in-memory key-value store.

Redis Page Cache for WordPress

So we rewrote our plugin, open sourced it on GitHub and released it on WordPress.org.

Installation and Configuration

The new plugin requires a little bit of extra configuration before it could be used, as well as a running Redis server and the Redis PECL extension. Both are likely to be available in pre-built packages for your favorite Linux flavor, for example in Debian/Ubuntu:

apt-get install redis-server php5-redis

After installing and activating the WordPress plugin, you’ll need to create a symbolic link to the advanced-cache.php dropin:

cd /path/to/wp-content
ln -s plugins/redis-page-cache/advanced-cache.php advanced-cache.php

Finally, enable page caching in WordPress with a constant in wp-config.php:

define( 'WP_CACHE', true );

The plugin has quite a few configuration options and some interesting features. You can read more about them in the full documentation on GitHub. Don’t forget to read through the Redis server configuration and purging cache sections.

Redis Performance

With Redis-based page caching, we’ve been able to solve some of the performance and maintenance issues we’ve had with our MySQL implementation. As a result, the same benchmark with our new plugin shows a 40% increase (10k vs 7k) in number of served requests in one minute with a 30% decrease in average response time (290ms vs 400ms):

Redis Page Cache Performance
Redis Page Cache Performance (HTTPS)

Note that this includes an HTTPS handshake for every request — we’re big believers in SSL here at Pressjitsu. On a regular HTTP the same test has shown ~ 20k requests served in one minute with an average response time of 150 ms.

Eliminating the networking factor (speed and latency) between Loader.io’s servers and ours, on our 1G plan we’ve seen about 1000 successful requests per second with the popular ApacheBench utility, and with our short-term Nginx-based cache configuration designed to smoothen traffic surges, the number goes up to about 6000 successful requests per second.

Disk Usage

What’s also interesting is how this change affected other resources. For example disk IO usage has dropped significantly, because unlike our previous MySQL implementation, Redis in our configuration does not use the disk at all:

Disk IO After Deploying Redis Page Cache
Disk IO After Deploying Redis Page Cache

The green line represents the disk IO, which in this case dropped from an average of 20 per second down to only 6. This graph was taken from a live website on our 1G plan with good cacheability, serving about 400k pageviews per month. If you’re wondering about the increase in average request size, that’s because MySQL is no longer performing frequent small requests to disk to retrieve our cache data.

PHP Response Times

The more interesting impact was on the overall upstream response times for PHP. This is due to the fact that PHP no longer touches MySQL when serving cached requests, which significantly increases InnoDB’s buffer pool efficiency for serving non-cache data.

PHP Response Timing
PHP Response Timing

The green line represents cache hits, while the blue line is for cache misses. While we’re happy we shaved off a few milliseconds off cache hits, but we’re more pleased that this allowed us to decrease response times for cache misses, in some cases up to 3 times faster!

Cache Hit Rate

One of the challenges we were faced with when moving to Redis is the total cache size — we no longer have the luxury of keeping as many cached items as we want and clean them up whenever because they’re no longer stored on disk.

With Redis we’re allocating a fixed and rather small amount of RAM (currently 32mb on our entry-level plans) for page caching, and if we outgrow that, Redis will evict older items to make room for newer ones on the fly. For WordPress sites with bad cacheability (remember PHP sessions?) this is bad business, much like any other caching solution. But for sites with good cacheability it’s not a problem at all.

Cache Hit Rate with Redis Page Cache
Cache Hit Rate with Redis Page Cache

To help deal with and debug cacheability, we’re also working on some CLI tools and commands for this new plugin that will output some stats and let users know about some cookie names and query variables they may want to ignore in their caching setup for a better hit rate. If you’re interested in testing out these tools here on Pressjitsu, please let us know via a support ticket and we’ll enable them for your server.

Why Not Persistent Object Caching?

It’s true that there are plenty of Redis-backed object caching plugins for WordPress, which can very well work with page caching solutions such as Batcache. But for many cases in-memory persistent object caching can actually hurt performance.

Plugins these days go crazy with options and transients and metadata, and with limited memory resources the cache backend can evict items developers wouldn’t expect it to. A simple “retrieve 10 latest posts” will result in 10 round trips to Redis for posts, another 10 for postmeta, another 10 or so for terms in addition to one MySQL query to retrieve the posh IDs. All of this versus just four MySQL queries without persistent object caching.

What’s worse is that if the object cache backend doesn’t have the requested items (which could have been evicted to make room for others), it could result in an additional 30 queries to MySQL. This is just one example.

We’re not saying persistent object caching is bad. It’s really good in targeted cases, where it’s being used on purpose, and not just slapped on. We do deploy persistent object caching for some customers that require it, but we can’t simply deploy it across the board and expect everyone’s performance to magically improve.

Contributing

The Redis Page Cache plugin is distributed under the GPL and is available on GitHub, so bring on your pull requests! If you run into any problems or have any questions, please feel free to open an issue on GitHub or drop us a note on support@pressjitsu.com.