Blazing speed with PHP's memcache extension
I've recently discovered something truly awesome that many of you might not know about: the memcache extension for PHP. The extension can be obtained from the PECL website. The memcache extension is an interface to the memcached daemon which was originally developed by Danga Interactive. It's purpose at the time was speeding up LiveJournal.com which is a very heavy-traffic website. In this article I'll explain what the memcache extension is and how it can help you increase the performance of any dynamic PHP website dramatically.
Installing the memcache extension
In order to install the memcache extension you need to install several packages on your server. Therefore this extension probably isn't for everyone because I don't think it's very widespread among providers offering shared hosting environments. What you need is the following packages *:- memcached, the daemon itself
- libevent
- If you use Linux, you'll want epoll
- And of course the memcache extension from PECL
The memcached daemon
After installing the memcache extension you need to start the memcached daemon. You can do this by issueing the following command:Using the memcache extension
The memcache extension has it's own section in the PHP manual in which the API is described. I guess not so many people have discovered this great extension yet since there aren't any user contributed notes to be found on these pages. However if you're a bit of a PHP programmer you'll probably find what you need here. In the examples here I'm keeping things simple. I'm assuming a memcached daemon running on the same machine on which the PHP project is running. The extension comes with both a procedural and an object oriented interface. Of course we're using the OO interface here, with PHP5. In order to make life as easy as possible we can create a little singleton:
include_once("constants.php");
// Memcache singleton object
class clsMem extends Memcache {
static private $m_objMem = NULL;
static function getMem() {
if (self::$m_objMem == NULL) {
self::$m_objMem = new Memcache;
// connect to the memcached on some
//host __MEMHOST running it om __MEMPORT
self::$m_objMem->connect(__MEMHOST, __MEMPORT)
or die ("The memcached server");
}
return self::$m_objMem;
}
}
$sMyString = "I'm going to be cached!";
clsMem::getMem()->set("mykey", $sMyString, false, 600)
or die ("Could not write to the cache");
- a key
- any serializable variable we'd like to cache, in this case it's a string
- a boolean whether we want to use on-the-fly zip compression using libz
- the cache expiry measured in seconds.
$sMyString = clsMem::getMem()->get("mykey")
or die ("Couldn't find the requested item in the cache!");
echo $sMyString;
function cachedSQL($sSQL) {
$sSQL = "SELECT some really heavy stuff FROM some table";
if($objResultset = clsMem::getMem()->get(MD5($sSQL)) {
// return the cached resultset
return $objResultSet;
}
else {
// assuming we have a PEAR::DB based database
// singleton handling the query
$objResultSet = DB::getDB()->query->($sSQL);
// Store the resultset in the cache
clsMem::getMem()->set(MD5($sSQL), $objResultSet, true, 600);
// return it
return $objResultSet;
}
}
Filed under: programming
Number of comments:
Number of trackbacks:
Tagged with: 







At 06 May '05 - 15:37 stefan wrote:
At 06 May '05 - 15:41 Marco wrote:
At 08 May '05 - 22:42 Henri wrote:
At 08 May '05 - 22:46 Marco wrote:
At 10 May '05 - 21:26 Jero wrote:
http://www.eaccelerator.net/HomeUk/
At 12 May '05 - 20:16 Max wrote:
If that’s the case, yes, that opens up some kick-ass opportunities, and some very interesting security considerations to boot. Certainly not something you’d want to enable for every vhost on a shared box… =]
At 12 May '05 - 20:26 Max wrote:
It seems to work under windoze:
Not that I care, of course =]
At 25 May '06 - 16:13 swinney wrote:
i’ve read the docs on this, but now i understand them. :)
good work!
At 28 June '06 - 23:12 walter wrote:
At 29 June '06 - 03:03 Marco wrote:
At 20 July '06 - 15:10 Lee wrote:
At 25 October '06 - 14:02 Andrew wrote:
When compared to MySQL’s query cache, the query cache has some caveats, most of which were mentioned above. Also remember that there’s usually a limit on the amount of memory a single process can address: for MySQL, this limits the size of each individual cache.
Of course, the same limitation applies to memcache, however, memcache has the additional advantage of allowing you to spread your data across several nodes. These nodes could be on the same machine, or multiple machines. Not only does this allow you to circumvent the memory limit (each memcache instance can address the maximum amount of memory), but it also allows you to spread the work around.
At 07 August '07 - 05:32 Ergün KOÇAK wrote:
At 02 September '07 - 22:11 Primoz Rome wrote:
1. What happenes when data in DB is changed? Then you’re always fetching cached date which can alredy be obsolete? How do you handle this cases?
2. Is it OK to cache small queries which always return same result (e.g. query that returns list of countries)?
and
3. why are you using MD5 for the key when setting to memcache?
Thanks,
Primoz
At 03 September '07 - 00:56 Marco wrote:
2. Yes
3. Anything sufficiently unique is fine. MD5 usually works fine for that.
At 09 October '07 - 13:45 Bryan wrote:
At 10 October '07 - 13:38 Bryan wrote:
At 28 November '07 - 05:06 Micheal wrote:
$memcache = memcache_connect(“localhost”, 11211);
function cachedSQL($sSQL) {
global $memcache;
if($objResultset = $memcache->get(md5($sSQL))) {
// return the cached resultset
echo “cachedn”;
return $objResultSet;
} else {
echo “not cachedn”;
$objResultSet = mysql_query($sSQL);
// Store the resultset in the cache
$memcache->set(md5($sSQL), $objResultSet, true, 600);
// return it
return $objResultSet;
}
}
At 03 December '07 - 23:04 John wrote:
“Note: Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, because they cannot be adequately represented in serialized state.”
http://ca3.php.net/manual/en/function.Me..
Try something like this:
http://lists.danga.com/pipermail/memcach..
John
At 03 December '07 - 23:51 John wrote:
function cachedSQL($sSQL, $time=null) {
// Try to find this SQL
if (($ary_results = clsMem::getMem()->get(MD5)) !== false) {
// Return the cached results array
return $ary_results;
// Otherwise we’ll have to actually do the query and cache the result
} else {
// Do they query
$obj_results = mysql_query($sSQL) or die(“Query failed: $sSQL. “ . mysql_error());
// Init the intermediate arrays
$ary_field_list = array();
$ary_results = array();
// Check if the resultset has 0 rows
if (mysql_num_rows($obj_results) > 0) {
// Fetch the Column information
while ($i <>set(MD5, $ary_results, true, $time);
return $ary_results;
}
}
At 03 December '07 - 23:56 John wrote:
Hereis the cachedSQL function for mysql_query:
function cachedSQL($sSQL, $time=null) {
// Try to find this SQL
if (($ary_results = clsMem::getMem()-
At 05 December '07 - 05:53 Micheal wrote:
while ($row = mysql_fetch_assoc( $result )) {
$objResultset[] = $row;
}
At 23 December '07 - 19:25 Ted Wood wrote:
(class)-(id)
so a typical key might be “SiteUser-14”.
The problem I ran into was that Site B had access to Site A’s records. This is not good. The solution I’m going to use is adding in an additional parameter unique to each site, so I’ll end up with this format:
(site-id)-(class)-(id)
That way, Site A can only look at records that begin with its site-id, “SiteA-SiteUser-14”.
Good thing I caught this early, since I’m dealing with records that are normally private and encrypted so I wouldn’t want to make them accessible to scripts that might be brute-force scanning the server’s memcache.
At 24 December '07 - 00:39 Marco wrote:
Depending on how secure this all needs to be you may even want to consider two different instances of memcached for your particular case to keep things even more separated.
At 01 September '09 - 01:41 Shafiq Rehman wrote:
In my case memCache takes more time than an SQL query. My SQL queries are highly optimized and return results very quickly than memCache.
Should I need to fine tune the memCache setings?
At 12 March '10 - 11:44 logan - memcached expert wrote:
At mysql.org they have a section of recorded webinars about SQL setting, scaling and optimizing settings “MySQL Scaling with Memcached”.
http://www.mysql.com/news-and-events/on-..
-L
At 28 July '10 - 12:13 Gergo wrote: