I have this setup running with 3 sites on a VPS and it seems to run without problems, and quite snappily at that. I’m using the Drupal Memcache module (aka. Memcache API and Integration), the PECL Memcache extension, Drupal 7 and Memcached itself of course (The daemon, not the PECL Memcached extension) all running on Ubuntu Server 12.04.
By default Drupal’s cache bins are kept in tables in the database, and here we will set up Drupal to use Memcached to store the cache bins instead. You can see what cache bins your Drupal site is using by looking for the database tables which begin with ‘cache‘. We will not store cache_form in Memcached as it should be stored in persistent storage to prevent losing any forms that your sites users may be half way with filling in. (Cache form is not just a cache).
I also avoid keeping cache_update in Memcached. cache_update is always stored in the database.
Just to clear up any confusion there is the Drupal Memcache module, the PECL Memcache extension (which we will be using), the PECL Memcached extension (which isn’t used in this setup) and the Memcached daemon, which is what the extensions are used to connect to. I would have preferred to use the PECL Memcached extension, as it supports sockets since version 2.0.0b1, unfortunately the Drupal Memcache module does not work with it as of yet. Additionally the Drupal Memcache admin module (which comes with the Drupal Memcache module) spewed forth errors upon viewing it’s stats page while using PECL Memcached, but was fine with PECL Memcache (apart from a more minor problem which is fixed below). I might do a post at a later date about using the PECL Memcached extension as I did get it working, eventually, by (hacking|patching) Memcache. (A modified version of the patch was committed, it is currently only available in dev releases as of 28/05/2013.)
I used sockets because A) It might (possibly should) be faster than going through the network stack, and B) when the Memcached daemon is told to use a socket, it disables it’s networking capabilities.
Final note, if you aren’t running as root, you either need to
su to get a root shell, or put
sudo in front of most of the commands. For editing config files I generally use nano, and you can get it display the line you are on by starting it with the -c switch like so:
nano -c /file/to/edit
Install & configure the Memcache daemon
You install the Memcached package (the daemon) with:
- apt-get install memcached
It is necessary to edit
/etc/init.d/memcached in order to automatically create a directory for the Memcached processes to place their sockets. I added this at roughly line 44:
- # Make /var/run/memcached directory
- if [ ! -d "/var/run/memcached" ]; then
- mkdir /var/run/memcached
- chown memcache /var/run/memcached
Bear in mind though, that it is possible for the above changes to be overwritten by an update to the Memcached Ubuntu package. You will generally get a warning if an update is about to overwrite your changes though.
As you can see from the usage notes in the
/etc/init.d/memcached file you need to copy
/etc/memcached.conf to a new file and edit it to create the configuration for a Memcached daemon:
- # The naming convention is memcached_myserver.conf, this will
- # create the config for a Memcached instance called myserver
- # You can name what you please
- cp /etc/memcached.conf /etc/memcached_myserver.conf
Now to edit
/etc/memcached_myserver.conf to our liking:
- # The memory limit is on line 23, it is measured in MB, it is probably safe to leave it at 64MB.
- # You can monitor it and increase it later if necessary.
- # Worth noting is that the daemon will not start out using this
- # much memory for storage, but will only grow to use this much space.
- -m 64
- # Comment out the default port on line 26 like so:
- # -p 11211
- #Comment out the IP address option on line 35 like so:
- # -l 127.0.0.1
- # At the bottom of the file add the location of your socket by specifying the -s switch:
- -s /var/run/memcached/memcached_myserver.sock
- # The name of the socket isn't important as long as you remember it for later.
- # I just stick to the config file convention, replacing .conf with .sock as I then always
- # know which socket belongs to which instance.
- # Finally add the -a switch to specify the octal file mode of the socket when it is created:
- -a 0766
- # You may not want the socket to be world writable, I have not set it up like that just yet.
If you only want to use one Memcached instance for all your Drupal cache bins you can move on, if not, you will need to repeat the above process create a configuration file for each of the Memcached instances you wish to use. You can assign multiple cache bins to one instance, or as some people like to do, you can create a Memcached instance for each cache bin, the advantage of the latter is that you can look at the statistics for each bin on it’s own. Remember to give each instance a unique socket (Just place them in the
/var/run/memcached directory to avoid problems with file permissions). You can also have multiple Drupal sites use the same Memcached instance.
Now start up Memcached and see if it is running:
- # Start all Memcached instances with:
- service memcached start
- # Alternatively start instances by name, for memcached_myserver.conf:
- service memcached start myserver
- # Stopping works the same way:
- service memcached stop # For all the instances
- service memcached stop myserver # For one instance
- # Check the Memcached log for errors, though it might not exist yet if nothing has been written to it.
- tail /var/log/memcached.log
- # Finally check if the instance is running:
- echo "stats" | nc -U /var/run/memcached/memcached_myserver.sock
- # Should return something like:
- # STAT pid 4668
- # STAT uptime 456843
- # STAT time 1342432534
- # ...
Install & configure PECL Memcache
This is easy, just do:
- pecl install memcache
Once that is installed you need to create
/etc/php5/conf.d/memcache.ini and add the following:
- # This enables the extension
The other configuration directives are listed in the PHP manual. Some are not useful to a single server running Memcached on sockets, as they pertain to a distributed setup. Currently using pecl to install the memcache extension will get you version 2.2.6, if you are feeling a little more daring you can install version 3, which is still in beta, like this:
- # If you haven't already installed PECL memcache
- pecl install memcache-beta
- # If you wish to "upgrade" to a beta release
- pecl upgrade memcache-beta
This does allow you to use more of the configuration directives listed in the PHP Manual, though Drupal Memcache does not support the binary protocol. You will also need to restart Apache if you are using mod_php, or mod_fcgid. If you are using PHP-FPM you will need to restart your PHP process. (Shameless plug on using Apache 2.2 and PHP-FPM over here).
If you are interested in using the PECL memcache's memcache.php for statistics reporting, see this post. memcache.php does a much better job than the memache_admin module discussed below. This is apart from the hit and miss statistics the memcache_admin module can provide on each page.
Install & configure the Drupal Memcache Module
The Drupal Memcache module is known as “Memcache API and Integration” on it’s project page. Download it, then we need to patch it with a patch from this issue. We need to patch it so that the memcache_admin statistics display correctly, so it won't break anything other than the statistics if you upgrade and the patch is not committed. I used the second patch as it contained the least cruft. To patch it just do this:
- # We need to change to the memcache_admin folder for patch no. 2 as it doesnt apply otherwise
- cd /path/to/memcache/memcache_admin
- wget http://drupal.org/files/patch-memcache-memcache_admin-socket-support.patch
- git apply -v patch-memcache-memcache_admin-socket-support.patch
If you don’t have Git installed you could make the changes by hand, it’s a pretty small patch.
Now, enable the memcache and memcache_admin modules. Check your status page to see if everything is alright, if it is you can continue to edit your settings.php.
- # Adds memcache as a cache backend
- $conf['cache_backends'] = 'sites/all/modules/memcache/memcache.inc';
- # Makes it so that memcache is the default caching backend
- $conf['cache_default_class'] = 'MemCacheDrupal';
- # Keep forms in persistent storage, as per discussed at the beginning
- $conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
- # Specify the memcache servers you wish to use and assign them to a cluster
- # Cluster = group of memcache servers, in our case, it's probably just one server per cluster.
- $conf['memcache_servers'] = array('unix:///var/run/memcached/memcached_myserver.sock' => 'default');
- # This assigns all cache bins to the 'default' cluster from above
- $conf['memcache_bins'] = array('cache' => 'default');
- #Alternatively, if you were using more Memcached server instances it would look like this:
- $conf['memcache_servers'] = array(
- 'unix:///var/run/memcached/memcached_myserver.sock' => 'default',
- 'unix:///var/run/memcached/memcached_myserver2.sock' => 'mycluster',
- # And then you could assign different bins to the second cluster
- $conf['memcache_bins'] = array(
- 'cache' => 'default',
- 'cache_bootstrap' => 'mycluster',
- 'cache_block' => 'mycluster',
- # If you wanted multiple Drupal installations to share one Memcache instance use the prefix like so:
- $conf['memcache_key_prefix'] = 'site_specific_prefix';
Now, if everything went as planned you can now visit your Drupal site as User 1 and see the Memcache hit and miss statistics on the bottom of each page, you can turn it on and off at drupal.example.com/admin/config/system/memcache, and the Memcache statistics overview page at drupal.example.com/admin/reports/memcache.
This post went on for much longer than I expected, I hope that someone finds it useful at least :S
If you made it this far, thanks for reading and drop your input below, especially if you think there is something wrong with the configuration.