Installing and Configuring Redis for Drupal 7, and other Memcached Alternatives
For years, we have been using and recommending memcached for Drupal sites as its caching layer, and we wrote several articles on it, for example: configuring Drupal with multiple bins in memcached.
Memcached has the advantage of replacing core caching (which uses the database) with memory caching. It still allows modules that have hook_boot() and hook_exit() to work, unlike external cache layers such as Varnish.
However, memcached has its limitations: It is by definition transient, so rebooting wipes out the cache, and the server can suffer if it has high traffic. It is also entirely memory resident, so to cache more items you need more RAM, which is not suitable for small servers.
For Drupal 7, there is a solution that does avoids this first limitation: Redis. It provides persistence, but not the second.
The following is a detailed guide to get Redis installed and configured for your server. It assumes that you are an Ubuntu Server 14.04, or the equivalent Debian release.
Installing Redis
First, download the Drupal redis module, which should go to sites/all/modules/contrib. You can do that in many ways, here is how you would use Drush for that:
drush @live dl redis
You do not need to enable any Redis modules in Drupal.
Then, install the Redis Server itself. On Debian/Ubuntu you can do the following. On CentOS/RedHat, you should use yum.
aptitude install redis-server
Then, install PHP's Redis integration. Once you do that, you do not need to compile from source, or anything like that, as mentioned in Redis README.txt file.
aptitude install php5-redis
Restart PHP, so it loads the Redis integration layer.
This assumes you are using PHP FPM:
service php5-fpm restart
If you are using PHP as an Apache module, then you need to restart it as follows:
service apache2 restart
Configuring Redis
Then in your settings.php file, you should replace the section for memcache which would be as follows:
$conf['cache_backends'][] = './sites/all/modules/contrib/memcache/memcache.inc';<br>$conf['cache_default_class'] = 'MemCacheDrupal';<br>$conf['memcache_servers'] = array('127.0.0.1:11211' => 'default');<br>$conf['memcache_key_prefix'] = 'site1';
And replace it with the following configuration lines:
// Redis settings<br>$conf['redis_client_interface'] = 'PhpRedis';<br>$conf['redis_client_host'] = '127.0.0.1';<br>$conf['lock_inc'] = 'sites/all/modules/contrib/redis/redis.lock.inc';<br>$conf['path_inc'] = 'sites/all/modules/contrib/redis/redis.path.inc';<br>$conf['cache_backends'][] = 'sites/all/modules/contrib/redis/redis.autoload.inc';<br>$conf['cache_default_class'] = 'Redis_Cache';<br>// For multisite, you must use a unique prefix for each site<br>$conf['cache_prefix'] = 'site1';
Cleaning Up
Once you do that, caching will start using redis. Memcached is not needed, so you should stop the daemon:
service memcached stop
And you should purge memcached as well:
aptitude purge memcached
And that is all there is to it.
Changing Redis Configuration
You can then review the /etc/redis/redis.conf file to see if you should tweak parameters more, such as changing maxmemory to limit it to a certain amount, as follows:
maxmemory 256mb
More below on this specific value.
Checking That Redis Is Working
To check that Redis is working, you can inspect that keys are being cached. For this, you can use the redis-cli tool. This tool can be used interactively, as in, you get a prompt and type commands in it, and results are returned. Or you can use the specific command as an argument to redis-cli.
For example, this command filters on a specific cache bin, the cache_bootstrap one:
$ redis-cli<br>127.0.0.1:6379> keys *cache_boot*
Or you can type it as:
$ redis-cli keys "*cache_boot*"
In either case, if Drupal is caching correctly, you should see output like this:
1) "site1:cache_bootstrap:lookup_cache"<br> 2) "site2:cache_bootstrap:system_list"<br> 3) "site3:cache_bootstrap:system_list"<br> 4) "site3:cache_bootstrap:hook_info"<br> 5) "site2:cache_bootstrap:variables"<br>...
As you can see, the key structure is simple, it is composed of the following components, separated by a colon:
- Cache Prefix
This is the site name in a multi site environment. - Cache Bin
This is the cache table name when using the default database caching in Drupal. - Cache Key
This is the unique name for the cached item. For cached pages, the URL is used, with the protocol (http or https) and the host/domain name.
You can also filter by site, using the cache_prefix:
$ redis-cli keys "*site1:cache_page*"
The output will be something like this:
1) "site1:cache_page:http://example.com/node/1"<br>2) "site1:cache_page:http://example.com/contact_us"<br>...
You can also check how many items are cached in the database:
$ redis-cli dbsize
The output will be the number of items:
(integer) 20344
Flushing The Cache
If you need to clear the cache, you can do:
$ redis-cli flushall
Checking Time To Live (TTL) For A Key
You can also check how long does a specific item stay in cache, in seconds remaining:
$ redis-cli ttl site1:cache_page:http://example.com/
The output will be the number of seconds:
(integer) 586
Getting Redis Info
You can get a lot of statistics and other information about how Redis is doing, by using the info command:
$ redis-cli info
You can check the full documentation for the info command.
But here is one of the important values to keep an eye on is used_memory_peak_human, which tells you the maximum memory that was used given your site's specifics, such as the number of items cached, the rate of caching, the size of each item, ...etc.
used_memory_peak_human:256.25
You can use that value to tune the maxmemory parameter, as above.
You can decrease the Minimum Cache Lifetime under /admin/config/development/performance to make the available memory fit that number, or the other way around: you can allocate more memory to fit more.
Monitoring Redis Operations In Real Time
And finally, here is a command that would show you all the operations that are being done on Redis in real time. Do not try this on a high traffic site!
$ redis-cli monitor
Performance Results
Redis performance as a page cache for Drupal is quite good, with Time To First Byte (TTFB) is ~ 95 to 105 milliseconds.
Notes on Fault Resilience
One of the big selling points of Redis versus Memcached, is that the former provides cache persistence across reboots.
However, as the documentation states, the default engine for Redis, RDB can lose data on power loss. That may not be a deal breaker on its own for a caching application. However, we found from experience, that loss of some cache records is not the only problem. The real problem was when a disk failure occurred, then repaired by the hosting provider, but the site was still offline, because Redis experienced data corruption, and refused to boot Drupal normally.
The other option is using AOF, which should survive power failures, but it has some disadvantages as well, including more disk space usage, and being slower than RDB.
Alternatives To Redis and Memcached
We did fairly extensive research for Redis and Memcached alternatives with the following criteria:
- Compatible With Redis or Memcached Protocol
We wanted to use the same PHP extension and Drupal Redis (or Memcached) modules, and not have to write and test yet another caching module. - Non-Memory Resident Storage
We want to reduce the memory foot print of Redis/Memcached, because they both store the entire key/value combinations in memory. But still wanted to get acceptable performance.
The following products all claim to meet the above criteria, but none of them worked for us. They were tested on Ubuntu LTS 14.04 64-bit:
MongoDB
Using MongoDB article for more details.
MemcacheDB
MemcacheDB is a Memcached compatible server which used the excellent Berkeley DB database for storage.
This MemcacheDB presentation explains what it does in detail.
It has an Ubuntu package right in the repository, so no need to compile from source, or manually configure it. It works flawlessly. The -N option enable the DB_TXN_NOSYNC option, which means writes to the database are asynchronous, providing a huge performance improvement.
Configuration in Drupal's settings.php is very easy: it is exactly like Memcached, with only the port number changing, from 11211 to 21201.
Alas, all is not rosy: it is not really a cache layer, since it does not expire keys/values based on time, like Memcached and Redis does.
Redis NDS
Redis-NDS is a fork of Redis 2.6, patched for NDS (Naive Disk Store).
It does compile and run, but when the line: 'nds yes' is added to the configuration file, it is rejected as an invalid value. Looking briefly in the source, we also tried 'nds_enabled yes', but that was rejected as well. So we could not get it to run in NDS mode.
ARDB
ARDB is another NoSQL database that aims to be Redis protocol compatible.
We compiled this with three different storage engines: The Facebook RocksDB did not compile to begin with. Google's LevelDB compiled cleanly, and so did WiredTiger. But when trying to connect Drupal to it, Drupal hanged and never came back with both engines.
SSDB
SSDB is also another NoSQL database that tries to be Redis protocol compatible.
It compiled cleanly, but had the same symptom as ARDB: Drupal hangs and never receives back a reply from SSDB.
There are a couple of sandbox projects, here and here, that aim for native integration, but no code has been committed so far in two years.
If you were able to get any of the above, or another Redis/Memcached compatible caching engine working, please post a comment below.
Resources
- A useful article on Redis persistence. Make sure you read this in conjunction with Redis' own documentation on presistence.
- Redis documentation on memory optimization.
- The Pantheon Redis instructions are useful, even though they are specific to their hosted service.
ArticlesRedisCachingmemcachememcachedMemcacheDBARDBSSDBRedis NDSDrupalDrupal PlanetMongoDB