Memcache is a tool which can cache objects in memory – and is often used for speeding up dynamic web applications. PHP has a built-in module for working with memcache, and its a simple and convenient way of introducing caching to your application.
PHP has a PECL module for talking to memcached – look up how to install for your system, but be aware that it isn't bundled. It's a good module to include on your system however, quite a few apps will take advantage of it where available.
A cache is like a temporary storage, like saying “remember toothpaste” to your 4-year-old when you head out to the shops. Then when you get there “What was I supposed to remember?” And get the answer back. The main difference is, memcache will actually give you back exactly what you gave it and not tell you “lollipops” in a hopeful manner instead!
Caching code in general will usually look something like this:
Working with Memcache
Memcache is object storage, objects are stored in a serialised manner in RAM, with a unique key to identify them. This means that you need a unique string to identify any object you may store in the cache. Primary keys work fine but look out for when you are storing multiple types of object in there - <object_type>_<primary_key> probably works better in that scenario.
The storage persists as long as the machine is on – a reboot empties the RAM and therefore clears the cache. You can also set how long a cached object is valid for. After that time, memcache will return false when you request your object and your code will fall through to its usual retrieval process.
Getting up and running with memcache is so easy that it’s one of those things you sit down to read up on and ten minutes later you realise you've actually already done it. Once you have memcache installed and set up with PHP, all you need is to create a memcache object to use in your application. Here's the code for mine:
To work with distributed memcaches, just make the call to addServer() multiple times. It is also possible to set a surprisingly large number of options with this function, including which port should be used, some connectivity settings, and even a weighting to say how likely this server is to be selected to store something. It’s a very powerful and flexible tool and in this tutorial we're only really looking at the top layer – but do read the manual pages and be aware that these options exist.
In PHP, the code you need to work with memcache is really minimal and wraps nicely around existing code without too much hassle. Consider my getUserById() function from earlier, here it is before I added caching:
We can wrap caching code around this, to firstly try to pull the object from the cache, and failing that to grab the object from the database and put it in the cache for next time.
All we've added here is a small conditional at the top of the function to immediately return the information if it exists in the cache – in this case the rest of the function doesn't need to be executed. Finally, just before returning from this function, we've added a line to store the user information in the cache for faster access next time.
Cache size and persistence
With an infinitely large RAM storage area for memcache to live on, theoroetically you could cache all the information in your application and just access it from there. In reality though there are limitations and knowing how memcache works will help you to get the most out of the tool.
When you add something to memcache, you can optionally set an expiry for it – stating how many seconds this cache is valid for. If this isn't specified then the object will persist unless it gets pushed out (more about that later). When picking expiry times, consider how often the information changes and could get outdated – if it’s very frequently, then consider not using the cache at all as this space could be better used storing other data.
When the cache becomes full, memcache will perform some magic to keep the data you are using the most. Things which aren't used often will eventually drop out of the space to be replaced with newer data. It can be tricky to work out how much cache is needed for a particular application – really the only way to get this right is to do some benchmarking and look at how the performance varies with cache size.
Caching is really useful for getting around bottlenecks such as having a database on a different server or a narrow pipe to a filestore. It is even more useful when that information doesn't change often – or if it doesn't matter too much whether the change is reflected straight away.
The example shown in this article was oversimplified – but I've used something very similar in a situation where third-party sites were pulling profile information from a shared central server and checking user validity with every user request. Users typically log in to one of the sites, browse around (sending a whole bunch of requests for their same profile information) and then move away – implementing memcache speeded up those subsequent requests hugely, and when they navigate away, their data either expires or gets pushed out of the cache by newer material.
Caching can also be useful for session data in PHP – so useful in fact that the memcache module comes with built-in support for storing session data in a cache. With the memcache module enabled, the php.ini directive session.save_handler can take the value "memcache" to store session data in memory rather than in files (the default option) or in the database.
Memecache as a tool
Memcache can be a big help but its not the silver bullet that will solve all performance problems. When added in the right place, it can produce very impressive results – especially for high-traffic applications. Its a great tool to have in the toolbox, and its really simple to get started with, so next time you need to improve the performance of an application, bear it in mind.