Website Performance Tools: How I Installed Memcached

28 February 2007 – 4:19 pm

We should all be lucky enough to have performance problems due to heavy website traffic.

“Plan for success” is one of my favorite cliches, and in that spirit, I’m trying to get/stay ahead of the curve on a website that’s growing in popularity, BUMPzee.

It not so much BUMPzee’s popularity put it in jeopardy of performance issues, it’s that it has widgets available for members to put on their own websites. Now, all of a sudden, BUMPzee’s server load is dependent hits from these widgets all over the place. And if one of those members gets hit with a Digg homepage mention, BZ’s servers get hit as well. Lately, a few high-traffic sites have put BZ widgets on their pages, and the last thing I want is to be the cause of slowdowns.

There are lots of ways to scale a web application, from throwing hardware at it, to optimizing database queries. I’ve been hearing a lot, however, about a software program called Memcached. It runs on one or more servers, and acts as a shared memory resource for any applications that may want to store information in fast-access RAM, like a long-running database query.

When to use Memcached

Memcached is great for dynamic database driven websites that retrieve data again and again from a database. Reading the same data over and over again from the database is a waste when you can store it in memory and use it from there. Even if the data gets updated fairly often, storing a cached version in memory for only 10 seconds can be highly effective if you get several pageviews during that period of time. And unless someone is saving data (at which point you’d automatically update the cache), nobody is going to notice that the data is 10 seconds delayed.

I’m just happy to have memcached in my toolbox. It will be valuable for when things get really busy and there’s a big query that gets run over and over

Installing Memcached

NOTE: Most of these operations have to be done by the root user on a server. It’s easy to follow instructions, but not always so easy to stay out of and get out of a jam if something breaks. All standard warnings about making backups of changed files, etc. apply.

I began the installation process and quickly ran into some problems. After some searching, trial and error, and persistence I did get it running. The good news is that once it is installed and running, it’s easy. And, if you have more than one server, you can run memcached on many servers acting as one shared resource.

I didn’t find, however, a how-to document with all the steps outlined on getting it running. So I put together those steps here.

There are two components to a memcached implementation. The server software that runs as a daemon on your server(s). That’s a simple application that you must download and install from source code. The other component is your application that uses is. There are libraries available for most web technologies: PHP, Ruby, Perl, etc. I use PHP.

Install Libevent

Memcached requires LibEvent, so I had to install that first. If you’re not sure, you can try installing memcache first and the configure process will tell you what you’re missing.

Go to the Libevent website and download the source files: Libevent

Once the file was downloaded, I used the following commands. Note, your filenames may differ if you have a newer version.


$ tar -xvf libevent-1.3a.tar
$ cd libevent-1.3a
$ ./configure
$ make
$ make install

Install memcache

Download the latest Memcached source code: Memcached


$ gunzip memcached-1.2.1.tar.gz
$ tar -xvf memcached-1.2.1.tar
$ cd memcached-1.2.1
$ ./configure
$ make
$ make install

All should be good now. However, when I run memcached, I get an error:

$ memcached
memcached: error while loading shared libraries: libevent-1.3a.so.1: cannot open shared object file: No such file or directory

I discovered somewhere that if I run a command like this, I get details about where it’s looking for the libraries:

$ LD_DEBUG=libs memcached -v
18990: find library=libevent-1.3a.so.1 [0]; searching
18990: search cache=/etc/ld.so.cache
18990: search path=/lib/tls/i686/sse2:/lib/tls/i686:/lib/tls/sse2 [...long path snipped...]
18990: trying file=/lib/tls/i686/sse2/libevent-1.3a.so.1
18990: trying file=/lib/tls/i686/libevent-1.3a.so.1
18990: trying file=/lib/tls/sse2/libevent-1.3a.so.1
18990: trying file=/lib/tls/libevent-1.3a.so.1
18990: trying file=/lib/i686/sse2/libevent-1.3a.so.1
18990: trying file=/lib/i686/libevent-1.3a.so.1
18990: trying file=/lib/sse2/libevent-1.3a.so.1
18990: trying file=/lib/libevent-1.3a.so.1
18990: trying file=/usr/lib/tls/i686/sse2/libevent-1.3a.so.1
18990: trying file=/usr/lib/tls/i686/libevent-1.3a.so.1
18990: trying file=/usr/lib/tls/sse2/libevent-1.3a.so.1
18990: trying file=/usr/lib/tls/libevent-1.3a.so.1
18990: trying file=/usr/lib/i686/sse2/libevent-1.3a.so.1
18990: trying file=/usr/lib/i686/libevent-1.3a.so.1
18990: trying file=/usr/lib/sse2/libevent-1.3a.so.1
18990: trying file=/usr/lib/libevent-1.3a.so.1
18990:
memcached: error while loading shared libraries: libevent-1.3a.so.1: cannot open shared object file: No such file or directory

There are probably lots of ways to get the library file to be found. I just created the following symlink to put it in a spot that memcached will find it in:

$ ln -s /usr/local/lib/libevent-1.3a.so.1 /lib/libevent-1.3a.so.1

Which does the trick nicely. Once I do that, memcached will run.

That’s the end of the installation

Running Memcached

$memcached -d -u nobody -m 128 127.0.0.1 -p 11211

simple. Now memcache is running, waiting for applications to store and retrieve information.

Install the Memcache PHP Extension

The memcache PHP extension is available as a dynamic library. Typically, these can be installed using PEAR and PECL. But those didn’t work on my server:

$ pear install memcache
No releases available for package "pear.php.net/memcache" - package pecl/memcache can be installed with "pecl install memcache"
Cannot initialize 'memcache', invalid or missing package file
Package "memcache" is not valid
install failed

From what I understand, PHP5 is required for using pecl, and in any case, that didn’t work either:

$ pecl install memcache
WARNING: channel "pear.php.net" has updated its protocols, use "channel-update pear.php.net" to update
downloading memcache-2.1.0.tgz ...
Starting to download memcache-2.1.0.tgz (19,567 bytes)
.......done: 19,567 bytes
4 source files, building
running: phpize
Configuring for:
PHP Api Version: 20020918
Zend Module Api No: 20020429
Zend Extension Api No: 20050606
/usr/local/bin/phpize: /tmp/tmpFqYI1O/memcache-2.1.0/build/shtool: /bin/sh: bad interpreter: Permission denied
Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF
environment variable is set correctly and then rerun this script.

ERROR: `phpize' failed

I spent a good amount of time trying to get these things running. Ultimately, I think that may be because my server has noexec on the /tmp directory for security purposes (which I highly recommend!). Anyway, instead of trying to figure that out, I installed it manually:

Manual Install of the memcache PHP extension


$ wget http://pecl.php.net/get/memcache-2.1.0.tgz
$ gunzip memcache-2.1.0.tgz
$ tar -xvf memcache-2.1.0.tar
$ cd memcache-2.1.0
$ phpize
$ ./configure
$ make
$ make install

Note the installation location on the make install command:

$ make install
Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20020429/

In order to get this extension to load, you need to add the command to the php.ini file

Since the above directory seemed odd to me and I had to configure PHP anyway, I moved the extension up one level. This requires an edit to php.ini. This was ok since I don’t have any extensions loading from anywhere else. You should confirm the same for your setup.

Here’s the change I made to php.ini:

; Directory in which the loadable extensions (modules) reside.
# extension_dir = "./"
extension_dir = "/usr/local/lib/php/extensions";

And I copied the memcache.so into that dir:

$ cp /usr/local/lib/php/extensions/no-debug-non-zts-20020429/memcache.so /usr/local/lib/php/extensions/

Once that’s there, we can add the dynamic extension to the php.ini file. There’s a section for extensions where I put this.

extension=memcache.so

and restart the web server.

Test PHP script

Once we’ve got things running, we need a test. This is a simple script that stores some data in the cache and retrieves it.

< ?php

$memcache = new Memcache;
$memcache->connect(’localhost’, 11211) or die (”Could not connect”);

$version = $memcache->getVersion();
echo “Server’s version: “.$version.”
\n”;

$tmp_object = new stdClass;
$tmp_object->str_attr = ‘test’;
$tmp_object->int_attr = 123;

$memcache->set(’key’, $tmp_object, false, 10) or die (”Failed to save data at the server”);
echo “Store data in the cache (data will expire in 10 seconds)
\n”;

$get_result = $memcache->get(’key’);
echo “Data from the cache:
\n”;

var_dump($get_result);

?>

And here’s the output of the working script:

Server's version: 1.2.1
Store data in the cache (data will expire in 10 seconds)
Data from the cache:
object(stdClass)(2) { ["str_attr"]=> string(4) “test” ["int_attr"]=> int(123) }

Do Something Useful

Now it’s up to you to figure out where the heavy lifting occurs on your web applications and lighten the load by storing stuff in memory.

Do it now before you need it. Good luck!

Additional Reading

Distrubuted Caching with Memcached
Use Server-Side Caching When Possible (memcached)
If You’re Not Using memcached You’re Doing It Wrong

If you enjoyed this post, please subscribe to my RSS feed

  1. 21 Responses to “Website Performance Tools: How I Installed Memcached”

  2. Scott,

    What kind of performance improvements have you seen?

    memcached + eaccelerator gave me about a 300x speed increase on an ad server.

    By ddn on Feb 28, 2007

  3. Jury’s out on that ddn. I was just so happy to get it running that I wanted to write about it before I forgot all the details.

    Tried it out in a few spots and got some 2x improvements — but we’re talking about milisecond execution times on DB hits, so there isn’t much room for improvement on those.

    I’ll follow up when I’ve got some meatier results.

    By Scott on Feb 28, 2007

  4. You’ll definitely see the difference as traffic ramps up. It may not be so much a speed thing as scalability. You should be able to drop the number of queries to the DB by several orders of magnitude.

    Have fun.

    By ddn on Feb 28, 2007

  5. what type of setup do you have for hosting your sites? I’ve never ventured outside of shared hosting, and never needed to.

    By mark from 45n5.com on Feb 28, 2007

  6. Hey Mark, we’ve got a number of dedicated servers. Nice for when you’ve got to do stuff like this.

    By Scott on Feb 28, 2007

  7. maybe when I grow up more ;-) thanks scott

    By mark from 45n5.com on Mar 1, 2007

  8. Scott — I was hit with the exact problem you described last week. The brand new Blog Window widget that I created became so popular that my server was getting hit at an average of 2-3 times per second. I didn’t expect the load to go up so fast. Unfortunately, this overwhelmed the hosting site I was using. I’m using ASP.NET so your trick doesn’t help me, however, I rearchitected by implementing the cache in the ASP.NET code. Also, upgraded to a dedicated dual-proc, 4GB system, so the CPU meter now barely budges even under heavy load.

    By Gene Kavner on Mar 2, 2007

  9. Great post… you may also want to start looking at lighttpd. Very much worth your time!

    Cheers!

    By fernando on Mar 5, 2007

  10. thanks fernando.

    Yeah, that’s next on the list. getting lighttpd set up for serving the static assets like images.

    By Scott on Mar 5, 2007

  11. You’d be surprise how well lighttpd with PHP does… and you can load balance php across servers, and now that you have memcached you can store sessions on memcached and things will fly… I can’t say enough good things about lighttpd.

    Here is a great post on their blog:
    http://blog.lighttpd.net/articles/2006/12/28/lighttpd-powers-5-alexa-top-250-sites

    By fernando on Mar 6, 2007

  12. Regarding this error:

    memcached: error while loading shared libraries: libevent-1.3a.so.1: cannot open shared object file: No such file or directory

    I tried making the symlink as you suggested (except for me, it was in lib64) and it worked, but it left a little bit of a “hack-like” taste in my mouth.

    I noticed the first line is ld.so.cache. With a little research, I found an alternative and less hack-tasting (imho) method: in /etc/ld.so.conf.d/ make a file called libevent.conf and write in this file the path to the libevent libraries (eg /usr/local/lib). Finally, run ldconfig (as root) and the cache get regenerated.

    The advantage of this method is that as the cache gets checked before the system path, it means the system does less “looking” for the file. In any case - both methods work.

    Thanks for this blog!

    By Nicholas Thompson on Mar 11, 2007

  13. It was a total hack, Nick, yeah.

    thanks for adding this. great info.

    –scott

    By Scott on Mar 11, 2007

  14. No probs - glad to help. I’ve already implemented this in my ThingyMaJig site. It brought page generation times from 400ms to just over 100ms. Thats MASSIVE!

    I’m currently (litterally - i’m doing it NOW) working with a friend to create an official module for Drupal. He’s made a very good start (the base for TMJ) and I’m extending it.

    By Nicholas Thompson on Mar 11, 2007

  15. Thank you for this article ; I couldn’t find the library not found error for the libevent. I’m sure this article is useful to dozens of people :-)

    By matthieu on Apr 24, 2007

  16. Hey Scott,

    Great work with the article, you saved me a ton of time in getting the memcacheed working with PHP!.
    I owe you a beer :) Keep up your good work.

    By Sudhir on May 2, 2007

  17. Glad it helped Sudhir!

    By Scott on May 2, 2007

  18. We memcached some internal API stuff about a month ago at b5media.com, and it drastically improved things. DB load was slashed by 2/3. I’m looking forward to caching more stuff!

    I’d suggest building packages out of libevent, memcached, and the PECL module to make it easier to manage your servers. My blog has some links on the latter, libevent ships with a .spec file, and memcached is only a couple of files.

    Sean

    By Sean on May 27, 2007

  19. Scott - What a lifesaver you are. Our site had some issues as described above last year and what a debacle. With memcache and your instructions for installation, we won’t run into this problem again. One respondent said he’d buy you a beer - heck, I’ll buy you dinner! Thanks.

    By MorganLighter on Jun 11, 2007

  20. As everyone knows, this conservative boy metrically hit close to some selective bonus black jack. Ah, this bonus fã¼r black jack is much more weird than the clinical blackjack boni. A government is grievously intensive. I read once, a content man blissfully reined into that ridiculous stage. Actually, a black jack boni is far more vivid than the sick bed. Goodness, a bonus black jack is much more unnecessary than some immense area.
    black jack boni - http://www.black-jack-boni.de/

    By black jack boni on May 2, 2008

  1. 2 Trackback(s)

  2. Apr 17, 2007: Links for 2007-03-08 [del.icio.us] | Gate911
  3. Oct 11, 2007: When Memcached Doesn’t Cut It - Website Caching Part II at Jangro.com

Post a Comment


Note: Your comment may be delayed for moderation. Sorry for the delay.