Storing your PHP sessions using memcached
August 25th, 2008 | by Guillaume Plessis |Using PHP sessions can be a problem when your PHP applications are load-balanced on many web servers. You can store them on a NFS export or recode the session_set_save_handler using a SQL backend for example. But there is no solution more efficient, more scalable, more performant and easier to deploy than using memcached…
Memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load…
Many well-known huge architecture (Facebook, Livejournal, Youtube…) are using it as memory caching to reduce the load on their servers. It can also be used to share PHP sessions among several servers. Let’s see how…
Installation
The first thing is to install the memcached server on your Debian server :
apt-get install memcached
Then, since the memcache PECL extension now provides its own session handler, it’s easy to plug PHP and memcached servers. Just install the appropriate extension (from Dotdeb) :
apt-get install php5-memcache
and change some of your PHP settings :
session.save_handler = files ; session.save_path = "N;/path"
to :
session.save_handler = memcache ; change server:port to fit your needs... session.save_path="tcp://server:port?persistent=1&weight=1&timeout=1&retry_interval=15"
That’s all! After relaunching your Apache2 server, your PHP sessions will be stored on the memcached server.
Tags: memcached

32 Responses to “Storing your PHP sessions using memcached”
By Alex on Oct 6, 2008 | Reply
I followed this guide step by step but I can’t store my sessions in memcached. The memcache module is configured (appears in php_info()) but when I try to do a session_start this fails.
By Guillaume Plessis on Oct 9, 2008 | Reply
It works without any problem.
Be sure that /etc/php5/conf.d/memcache.ini contains this line :
extension=memcache.so
and that your session.save_path is well set in your php.ini. For example :
session.save_path=”tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15″
Check your firewall settings if you installed one.
Then stop and start Apache (not restart) and display a phpinfo(), it should work.
By Joao Alfredo on Dec 5, 2008 | Reply
Hello Guillaume,
I was looking for something like memcached to use it with php_sessions.
It looks amazing!
But some doubts arose and I think you can help me.
Do you know if its possible to have control over the sessions in memcached ?
Like to know the number of sessions and the possibilite to kill a session.
Thanks.
By Guillaume Plessis on Dec 5, 2008 | Reply
It could be possible to manipulate sessions directly by using the memcache_* functions. Take a look at the source code of the memcache session handler, it seems to be a Memcache::delete call :
http://cvs.php.net/viewvc.cgi/pecl/memcache/memcache_session.c?revision=1.9&view=markup
By Ruben Vandille on Dec 12, 2008 | Reply
The same considerations are valid for other save_handler settings … the default ‘file’ handler for example:
$dh = @opendir(ini_get(’session.save_path’));
while (false !== ($file = readdir($dh))) {
if (strstr($file, ’sess_’)) {
@unlink(unlink(ini_get(’session.save_path’) . “/$file”));
}
}
By Son on Dec 14, 2008 | Reply
Like Alex, I am not able to get the memcache to work with my session handler. I am currently running two VM’s. One for the memcache and one for the Front-end server. Both VM’s are running Debian Etch with Apache, and php5-memcache installed.
The MemCached VM is located at xxx.xxx.xx.xxx and running on port 11211.
On my front-end server, I have set the session handler in php.ini as below:
session.save_handler = memcache
session.save_path = “tcp://xxx.xxx.xx.xxx:11211″
When I run session_start(), I get the following warning: “Warning: session_start() [function.session-start]: Cannot find save handler memcache”.
Does anyone have any idea why this is happening? Your help is greatly appreciated.
By Son on Dec 14, 2008 | Reply
In addition to my last post:
Strange thing is that it works fine when I use the php’s MemCache api’s.
For example, from my front-end server, I am able to run the following code without any problems:
$memcache = new Memcache;
$memcache->connect(‘xxx.xxx.xx.xxx’, 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, 5000) 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);
By Guillaume Plessis on Dec 14, 2008 | Reply
@Son : Could you please provide a phpinfo() so that I check that everything is ok?
By Son on Dec 14, 2008 | Reply
Hi Guillaume,
Thanks for the quick reply. At the moment, the VM’s are not in a public domain. Nonetheless, below is the phpinfo that pertains to memcache:
System Linux fe1 2.6.18-6-amd64 #1 SMP Wed Oct 15 10:07:11 UTC 2008 x86_64
Build Date Sep 30 2008 18:29:09
Server API Apache 2.0 Handler
Virtual Directory Support disabled
Configuration File (php.ini) Path /etc/php5/apache2/php.ini
Scan this dir for additional .ini files /etc/php5/apache2/conf.d
additional .ini files parsed /etc/php5/apache2/conf.d/mysql.ini, /etc/php5/apache2/conf.d/mysqli.ini, /etc/php5/apache2/conf.d/pdo.ini, /etc/php5/apache2/conf.d/pdo_mysql.ini
PHP API 20041225
PHP Extension 20060613
Zend Extension 220060519
Debug Build no
Thread Safety disabled
Zend Memory Manager enabled
IPv6 Support enabled
Registered PHP Streams zip
Registered Stream Socket Transports tcp, udp, unix, udg, ssl, sslv3, sslv2, tls
Registered Stream Filters string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, convert.iconv.*, bzip2.*, zlib.*
apache2handler
Apache Version Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch13 mod_perl/2.0.2 Perl/v5.8.8
Apache API Version 20051115
Server Administrator webmaster@local.sandbox
Hostname:Port local.sandbox:0
User/Group www-data(33)/33
Max Requests Per Child: 0 – Keep Alive: on – Max Per Connection: 100
Timeouts Connection: 300 – Keep-Alive: 15
Virtual Server Yes
Server Root /etc/apache2
Loaded Modules core mod_log_config mod_logio prefork http_core mod_so mod_alias mod_auth_basic mod_authn_file mod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_autoindex mod_cache mod_cgi mod_dir mod_env mod_mem_cache mod_mime mod_python mod_negotiation mod_perl mod_php5 mod_rewrite mod_setenvif mod_status
memcache
memcache support enabled
Active persistent connections 0
Revision $Revision: 1.39 $
session
Session Support enabled
Registered save handlers files user
Registered serializer handlers php php_binary wddx
Directive Local Value Master Value
session.auto_start Off Off
session.bug_compat_42 On On
session.bug_compat_warn On On
session.cache_expire 180 180
session.cache_limiter nocache nocache
session.cookie_domain no value no value
session.cookie_httponly Off Off
session.cookie_lifetime 0 0
session.cookie_path / /
session.cookie_secure Off Off
session.entropy_file no value no value
session.entropy_length 0 0
session.gc_divisor 100 100
session.gc_maxlifetime 1440 1440
session.gc_probability 0 0
session.hash_bits_per_character 4 4
session.hash_function 0 0
session.name PHPSESSID PHPSESSID
session.referer_check no value no value
session.save_handler memcache memcache
session.save_path tcp://xxx.xxx.xx.xxx:11211 tcp://xxx.xxx.xx.xxx:11211
session.serialize_handler php php
session.use_cookies On On
session.use_only_cookies Off Off
session.use_trans_sid 0 0
Thanks in advance!
By Guillaume Plessis on Dec 14, 2008 | Reply
@Son Your memcache version does not match mine, so please ensure you did install php5-memcache and all the php5-related packages from Dotdeb. You should obtain the same result as http://www.moolfreet.com/phpinfo.php
By Son on Dec 17, 2008 | Reply
Thanks. I’ll look into this.
By Son on Dec 17, 2008 | Reply
Guillaume,
I followed your steps and still, I am getting the same results.
Any idea?
-Son
By Guillaume Plessis on Dec 17, 2008 | Reply
@Son : something’s wrong, you should se “Version : 3.0.2″ in the memcache section of your phpinfo(). What is the output of :
dpkg -l ‘*php5*’
You should only see packages from Dotdeb. Debian’s php5-memcache does not include the memcache session handler!
By Lewis Carr on Jan 18, 2009 | Reply
Check that there is only 1 session save path, I had 2 in my php.ini and this caused the problem.
By Laph on May 8, 2009 | Reply
An important side-note: Debian cleans up sessions using a cron job – and therefore disables PHP’s internal session cleanup by setting “session.gc_probability” to 0 (zero). You should set this to something > 0 when using memcached as session storage.
By Guillaume Plessis on May 9, 2009 | Reply
@Laph : thanks for this useful comment.
By Lazy on Jun 1, 2009 | Reply
@Laph you shouldn’t set touch that, each record in memcached has its ttl, when it’s reached object is automagicly removed from cache so php has no garbage to collect
By bogdan on Jul 26, 2009 | Reply
php.ini directive should be session.save_handler = memcached NOT memcache. works ok now !
By Guillaume Plessis on Jul 27, 2009 | Reply
@bogdan : That is strange. Dotdeb provides the “memcache” extension and the save_handler shoud be named so, as said in the doc :
http://pecl.php.net/package/memcache
http://www.php.net/manual/en/memcache.ini.php
On the other side, memcacheD and the so-called save_handler is a better but newer extension. Dotdeb does not provide it (yet).
http://pecl.php.net/package/memcached
By Sean on Sep 3, 2009 | Reply
Hi! I use memcache to keep php-session for a while, and I met this problem too yesterday.
It happened after I setup php-java-bridge on my Contos 5.2, and I found that is because I edit my php.ini to use [Java] section.
However, when I remove the [Java] section, and restart httpd, the memcache session worked again.
Hope that helps sombody^^
By Laph on Dec 18, 2009 | Reply
@Lazy (& Guillaume):
To clarify this: Does the TTL of the PHP-Session depend on memcached’s TTL or on the Session-GC Stuff in php.ini?
I think it should be (and hopefully it is) the php.ini settings. Changing the session.save_handler should NOT have any impact on the session TTL/GC.
And in this case, my comment is right.
By lazy on Dec 18, 2009 | Reply
@Laph:
session.gc_probability has nothing to do with
setting session ttl, my point was that
memcached has it’s own gc whith will remove old objects and turning on php’s gc is pointless
By Laph on Dec 18, 2009 | Reply
@Lazy:
????
According to PHP-Manual:
- session.gc_maxlifetime specifies the number of seconds after which data will be seen as ‘garbage’ and potentially cleaned up.
- And session.gc_probability and session.gc_divisor manage the probability, that the cleanup process is started.
Therefore, with:
- session.gc_probability = 1 and
- session.gc_divisor = 100
there’s a 1 Percent chance “per Klick” that all sessions older than
- session.gc_maxlifetime Seconds are deleted.
IMHO, that’s how PHP manages Session-Expiration (with “files” as session handler) and changing the session.save_handler to “memcache” should not change this behaviour.
Of course in memcached every element can have it’s own TTL – but the PECL memcache Extension should mimic PHP’s “original” behaviour – don’t you agree?
By lazy on Dec 18, 2009 | Reply
@Laph
It can’t because, you can’t list items in memcached, so php can’t do session gc
php sets ttl’s on session objects in memcached,
and they are removed by memcached not by php’s gc
so enabling php gc is pointless
By Laph on Dec 18, 2009 | Reply
@Lazy:
Ok, understood – even though I don’t like it. So, last question:
How/Where do I set the time, a Session shall be seen as expired when using memcached as session.safe_handler? Just in case someone has a web-app that needs a quite long Session expiration time. There seems to be …uhm, nothing to take any influence on that – making “memcached” useless as session handler for this kind of apps because of a (possibly) too short Session TTL for PHP.
By lazy on Dec 18, 2009 | Reply
@Laph:
memcached uses ttl provided by gc_maxlife so it can be as long as You wish as far there is space avaiable on memcached server
By olivier on Feb 18, 2010 | Reply
Thank you Guillaume for these instructions and for providing us with the great dotdeb packages.
The php5-memcache module included in the dotdeb packages for lenny (which is based on v3.0.4 of memcache) does not work as expected for sessions redundancy on two memcached servers. The problem is not specific to the dotdeb package but is indeed due to the original v3.0.4 code of pecl/memcache:
http://pecl.php.net/bugs/bug.php?id=16061&edit=1
I spent a couple of hours in order to understand what was going on and I wanted to let you know about this problem in order to save your own hair. As a workaround you can install v3.0.1 from stable.
By Guillaume Plessis on Feb 19, 2010 | Reply
@Olivier : thanks for this feedback. I’ll fix it (by downgrading to v3.0.3) in my next uploads