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.
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.
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.
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
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”)); } }
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.
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);
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!
Guillaume,
I followed your steps and still, I am getting the same results.
Any idea?
-Son
@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!
@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
@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
@Lazy: ???? According to PHP-Manual:
Therefore, with:
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?
@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
@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
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.
Thanks for your article, perhaps you could add some more information:
We tried to save our sessions with memcache, and this works fine most of the times.
But there’s a strange problem. Usually, the average session startup time is only a few milliseconds, but sometimes a session startup needs about 10 Seconds!!!.
Do you have experience with this kind of problems?
The same problem occurs to me. Below is the code i used: ini_set(‘session.save_handler’, “memcache”); ini_set(‘session.save_path’, “tcp://xxx.xx.xx.x:11211”); session_start(); echo ini_get(“session.save_handler”);
Warning: ini_set(): Cannot find save handler ‘memcache’
If i change save handler from
memcachetomemcached, page does not load at all.Please help?
@Guillaume Plessis: Sorry Guillaume, it does not work. I tried to initialize a session on x server pointing memcache path on z server and i could use session array on x. But when i started session using session_start an tried to print on y server pointing memcache path on z. It does not work.
I could not able to maintain session on server x and y. Do you have any solution or a blog i can refer to?
@Guillaume Plessis : When i telenet memcache server Z from server Y, codef0rmer: telnet Z’s IP 11211 Trying Z… Connected to Z Escape character is ‘^]’.
But i have installed memcache on X server itself as there is no different server for memcache. Is this happening because of this scenario?
I have installed memcache on server 192.168.0.1 to store sessions.
In firefox, i accessed 192.168.0.2/index.php: ini_set(‘session.save_handler’, “memcache”); ini_set(‘session.save_path’, “tcp://192.168.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15″); session_start(); $_SESSION[‘username’] = ‘foobar’; print_r($_SESSION); //Prints above defined session array
Again in firefox in new tab, i accessed 192.168.0.3/index.php: ini_set(‘session.save_handler’, “memcache”); ini_set(‘session.save_path’, “tcp://192.168.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15″); session_start(); print_r($_SESSION); //It should print above defined session array
But it does not work in my case. Will it affect as I m setting save handler and path using ini_set?
Hi guys,
My Server Debian 6, i use PHP 5.3.6 and Memcached version 2.0.0b1.
ı traying start session but memcache gived error:
Apache error log msg:
PHP Warning: Unknown: Failed to write session data (memcached). Please verify that the current setting of session.save_path is correct (tcp://127.0.0.1:11211) in Unknown on line 0
I’m and more than 5K people need solutions for this problem. :)
it seems that many site are confused between memcache and memcached.
for memcached : http://fr2.php.net/manual/en/book.memcached.php
or http://www.solanara.net/solanara/memcached the 2nd one is not in english, but realy helpfull
Problem with using memcached for session backend is that it does not quarantee to retain data until its TTL expires. It can freely expire entries prematurely to free up memory for new data to be stored. By storing session data there, you might end up losing your session or parts of your session without knowing it has happened.
To be provide reliable solution, you need to store data redundantly somewhere else or you need persistent storage for you sessions. One lightweight solution is Scache (http://scache.nanona.fi).
Hey,
I am experiencing several segfaults while using memcached as like as explained in this article. Does anyone else share this experience? Any ideas on how to solve this?
It looks like after a certain amount of load or requests or whatever the setup just crashes and no new sessions can be stored or old ones be requested.
Hi guys,
Solution between using memcache vs memcacheD (in php.ini) is:
; Use protocol for memcache session.save_handler = memcache session.save_path = “tcp://localhost:11211”
; Do not use protocol for memcacheD session.save_handler = memcached session.save_path = “localhost:11211” enabled Version => 1.0.2 libmemcached version => 0.44 Session support => yes igbinary support => no
Hello there! This post could not be written much better! Looking at this article reminds me of my previous roommate!
He always kept talking about this. I most certainly will forward this post to him. Pretty sure he’s going to have a great read. Thanks for sharing!