Categories
PHP Programming

Getting Web Scale with Memcached

The web is huge, and there are a lot of people on it. Day and night, millions upon millions of people are on the web surfing, commenting, and contributing. Normally your blog gets a few hundred visitors a day ( a few thousand on a good day ), but what happens when that number increases? Can your database server handle all that load? Will Apache come screeching to a halt due to all of the requests? The answer is probably yes, unless you implement some form of caching. Many years ago this wasn’t a huge problem, but as the web and it’s user base has grown, so has the problem of “web scale”.

Memcached

Memcached is a pretty simple concept. Just as the name implies, it’s a caching system that stores stuff in memory. That’s really all you need to know to get started. If you’re interested in learning more, check out the Memcached home page.

PHP Memcache

As this is mostly a PHP blog, I’m going to show you how to use Memcached with the PHP Memcache module. While this tutorial is language specific, the concepts here can be applied to any language to increase the speed of your web pages. That being said, the first step is to get Memcached installed on your machine. There are a ton of tutorials out there on the web for this, so I’m going to leave that as an exercise for you. Once that’s installed, you should check out my guide for getting the PHP Memcache module installed on XAMPP, that way you can run this tutorial locally.

Step 1: Make the connection

This step is pretty straight forward. If you can’t connect to your caching server, you can’t cache. If the connection is successful, continue trying to cache. Otherwise, just query your database as normal.

$memcache = new Memcache;
$memcache->connect("my.memcached.server", 11211);

Step 2: Cache something

For this step, the only potential “gotch-ya” is that the your identifier must be unique, and time to expire is in seconds.

$myValue = "hello world!";
$memcache->set("Hello World", $myValue, false, 60*60*24);

Step 3: Retrieve an item from the cache

$myValue = $memcache->get("Hello World");
echo $myValue;

Step 4: Putting it all together

So how does all this work in conjunction with your web app? The basic workflow for using caching is the following:

  1. Does my item exist in cache> (This satisfies determining if a connection to the cache has been made as well.)
  2. If so, get the item and store in a variable.
  3. If not, get the item from the database.
  4. Store the item for later use.
$memcache = new Memcache;
$memcache->connect("my.memcached.server", 11211);
 
$arrayVals = $memcache->get("My Identifier");
if(!$arrayVals) {
        //Note: This assumes that the data in the table doesn't change
       // and that it is fairly small in size.
	$query = "SELECT * FROM myTable";
	$result = mysql_query($query);
	while($row = mysql_fetch_array($result)){
		$arrayVals[] = $row;
	}
	$memcache->set("My Identifier", $arrayVals, false, 60*60*24);
}
 
foreach($arrayVals as $val) {
	print_r($val);
}

If you’re following carefully, you can see that the first time through the data will get pulled out of the database. However, for the next 24 hours the data will be coming from the Memcached server. It’s little tricks like this that can help your site survive being featured on Reddit. Moral of the story: If your site is slow because of volume, try caching almost everything and you should have noticeable improvements.

By Jack Slingerland

Founder of Kernl.us. Working and living in Raleigh, NC. I manage a team of software engineers and work in Python, Django, TypeScript, Node.js, React+Redux, Angular, and PHP. I enjoy hanging out with my wife and son, lifting weights, and advancing Kernl.us in my free time.

23 replies on “Getting Web Scale with Memcached”

So you’re saying caching = web scale?
Sweet!
I was wondering how I could get rid of the cluster, the DB admins, the layered architecture, the templates, and the load balancer.

You are caching the result for 24 hours, yet there is no guarantee that your query will return the same data for those 24 hours. Additionally memcache has default object size limitations, so large resultsets may not fit in cache at all.

For result sets like this, smaller cache timeframes are usually a better idea. For single rows in the database, longer rows can be cached indefinitely and expired on delete/update.

@Dev Guy, Adodb is a database abstraction layer, but the need for explicit memcache calls remains as Adodb doesn’t do any of that for you.

@Jack Slingerland, a typo: “Does my item exist in cache> “

Why not just continue to write PHP as usual and let an external caching server like Varnish do the front end caching? With ESI (standard supported by Varnish) you can even cache individual page fragments.

What if.. when user comments on our blog but we have cached data before his comment.

It depends on your situation, but you could expire your comment cache when a new comment is posted. This may not be the best choice though. Can you elaborate a bit?

Comments are closed.