How to set up the Memcached PHP client library on CentOS 5

As we are currently building community features for our game download deal discovery site Deals4Downloads.com, I started investigating Memcached as a caching and session storage option. There are already many blog posts out there about this, but as many of them are unclear or even misleading, and I stumbled into every gotcha out there along the way, I thought I’d share some helpful tips here on how to get it all running. I’ll explain below what you’ll need to get Memcached along with PECL/Memcached (note the “d”) for your PHP site on CentOS 5.5. I’m not a pro sysadmin and I won’t go into every detail, but you’ll get the gist.

Memcache, Memcached, what’s with the name?

There are two parts to this equation: a server component and a PHP client component. You will need both. For the PHP client, there are two options, one of which even shares the name with the server component, which has caused a good deal of confusion.

Installing and setting up the Memcached server

You’ll need to install the Memcached server component first to be able to store and read values. Fortunately, this is the easy part: install package, configure and start server, add firewall rule to secure server, done.

Installation

Memcached is available as a ready-made package in my favorite repository, Remi, so we can install it with:

yum --enablerepo=remi install memcached

This should hopefully proceed without any problems. If you don’t have the Remi repository, you should first add it to your system, or use the repo of your choice.

Configuration

Next we need to edit the server’s configuration, start it and add it to the system start configuration. As far as I see it, you have two options here: either use the provided start script from the RPM, or add your own. You can set several parameters, like the IP and port that the service runs on, the user, and the amount of memory assigned (keep in mind that this is a fixed value).
# Option 1: edit and use the RPM start script
#adapt options here, like memory available
vi /etc/init.d/memcached
# start service
/etc/init.d/memcached start
# add to system boot config
chkconfig memcached on

# Option 2: start server manually and add custom start command to /etc/rc.local
# start server as daemon
/usr/bin/memcached -d -m 1024 -u httpd -l 127.0.0.1
# next, add the above command to /etc/rc.local to make it run at boot-time

A word about the parameters shown above:
-d start as daemon
-u user name for Memcached (adapt to your needs)
-m amount of memory assigned, in MB
-l (this is an L) IP address to listen on

Making it more secure

I’ll assume you will use your Memcache server only locally. It’s a good idea to add an IpTables rule to block all outside requests to this server. Add a line like this to your IpTables config (I won’t show this in detail here):
-A INPUT -p tcp --dport 11211 -j ACCEPT
If you want to set up a dedicated Memcached server and access it from another server, you will have to change the above accordingly.

Testing your Memcached server

Let’s test our new server a bit. I’ll show you some tools with output from my test server below:
# Is the service running?
root@D4D-TEST01 ~: netstat -tap | grep memcached
tcp 0 0 *:11211 *:* LISTEN 29441/memcached
tcp 0 0 *:11211 *:* LISTEN 29441/memcached

# see some stats with memcached-tool (installed along with RPM):
root@D4D-TEST01 ~: memcached-tool 127.0.0.1:11211 stats
#127.0.0.1:11211 Field Value
accepting_conns 1
auth_cmds 0
auth_errors 0
bytes 1867
bytes_read 81117
bytes_written 54550
[... etc]

Let’s connect with Telnet and set and get a value. You can set values with “set [keyname] [flag] [expirytime] [bytes]” and get values with “get “. If you set a value, you specify the keyname and the options first, press Enter, and then specify the value on the next line. You can read more about these commands here for example.

root@D4D-TEST01 ~: telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set mykey 0 900 6
mydata
STORED
get mykey
VALUE mykey 0 6
mydata
END

This is a bit clumsy of course, and what we really want is to set values from PHP. Time to install the PHP client component.

Again: Memcache, Memcached – what’s up?

This is where the confusion starts: there are two PHP client libraries available (both in PECL): one is called “Memcache” (or PECL/Memcache) and one is called “Memcached” (or PECL/Memcached). Yep, the second one is named exactly like the server. For a comparison, see for example here and here. The short of it: PECL/Memcache is older, less actively developed, and more widely used. PECL/Memcached relies on the libmemcached library, is newer and has more features. Most blog posts you’ll find are about PECL/Memcache, and that can be a bit misleading if you want to start out with PECL/Memcached.
After weighing my options, I decided to go with PECL/Memcached, and I’ll show you how to get it below.

Installing PECL/Memcached

If you just want the current stable version, get it from a suitable RPM. You will need libmemcached, too.

yum --enablerepo=remi install libmemcached
yum --enablerepo=remi install php5-memcached

After reading about some bugs in that version, I decided to use the current beta though, so I had to get it from PECL, which proved to be a bit more challenging. To make a long story short, you will definitely need zlib and libmemcached first, and probably their development libs as well (plus PECL of course):
yum --enablerepo=remi install zlib zlib-devel
yum --enablerepo=remi install libmemcached libmemcached-devel
pecl install memcached-beta

That should do the trick. You might have to add
extension=memcached.so

to your php.ini, if it’s not there already. If you call up phpinfo() (after restarting Apache), it should look like this:
phpinfo output for PECL/Memcached

Testing, again

So let’s test our new client with a little PHP script:
<?php
$mc = new Memcached();
$mc->addServer('localhost', 11211);
$mc->set('testkey', 'Hello there');
echo $mc->get('testkey');

Keep in mind that the APIs for Memcache and Memcached are very different, so most examples you see on the net won’t work for PECL/Memcached. The correct version of the documentation (as opposed to the one for Memcache) is here.
If you want to use persistent connections, make sure that you only add a server when none is defined yet, lest you end up with hundreds of them:
if (!count($mc->getServerList()))
$mc->addServer("localhost", 11211);

That’s about it. You now have a working Memcached setup and can use it for your caching purposes.

You can also use Memcached to store your sessions, but that will be covered in my next post.


About this entry