Categories
Documentation PHP

Storing your PHP sessions using memcached

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.

76 replies on “Storing your PHP sessions using memcached”

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.

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.

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!

@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!

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.

@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

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^^

@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.

@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:
– 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?

@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

@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.

@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:
– it is possible to add multiple memcached-servers to the pool, just add them into save_path commaseparated
– there are some interesting settings:
memcache.chunk_size
memcache.allow_failover
memcache.max_failover_attempts
memcache.hash_strategy
memcache.hash_function

I can’t save my sessions in memcached. The memcache appears in php_info(), the memcached daemon already started and I can execute session_start().
When I try to save sessions with $_SESSION[‘data’]=’blabla’ then I open new page, $_SESSION[‘data’] contains no data.
No error appears in log file.
somebody can help me pls?

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 `memcache` to `memcached`, 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?

@codef0rmer : did you restart your HTTP server on Y server? Do you see the memcache extension in a phpinfo() on Y server? Does a “telnet ipofmemcacheserver 11211″ work from the Y server?

@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?

@Guillaume Plessis:
Do you have any practical source code which worked in your case?
Did you able to make your session persistent over multiple servers before writing the blog?

@codef0rmer : of course I did! just by setting (in /etc/php5/apache2/php.ini) the session.save_handler to “memcache” on all my identical webservers and by setting session.save_path to the same memcache server. After a Apache stop/start, all worked well.

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. 🙂

this is overhead – if it is just for the session files, mount your /tmp to a ramdisk
tmpfs /tmp tmpfs defaults 0 0

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).

@Stefan : thanks for this notice and for sharing scache. It’s clear that using Memcached to store PHP sessions requires some precaution to avoid data loss : monitoring of the available key space and redundancy.
Antoher performant solution for persistent session storage is Redis. FYI, the phpredis extension (php5-redis package) has a built-in session handler.

Very good to know that php5-redis module is phpredis from Nicolas FF. I have just updated all my php5 packages, installed php5-redis and successfully tested it.
I recommend using Redis as an in memory/persistent cache for php sessions, instead of memcached’s exclusively in memory cache, for the sake of not loosing sessions’ data due to the cache rotation strategy used by memcached.

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

This is unnecessary. The sessions in memcached are inserted with an expiry time based on session.gc_maxlifetime and don’t need cleaning up. The memcache daemon handles that all on its own.

If you run out of storage space wherever you store your sessions you will end up with the roughly same problem as when you run out of space in memcached. One will probably hang or throw a Fatal error while the other will silently lose your user’s sessions. One affects users creating a new session, the other affects the stalest sessions stored. Choose the failure mode you can live with and monitor to make sure you don’t need it.

I am using LAMP server.
Could you please tell me the steps to follow to make memcached to work onto my local server

The only useful comment… Thank you Roman! *it’s all about tcp:// and no tcp:// on memcache vs memcached….

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!

Good short guide and discussion in comments. After many many millions of session files (was created faster than they could get deleted by the cron), this solved everything for me.
Thanks Guillaume

beautiful and working. nicely. wordpress, total cache, mo cache, thesis cache, apc and mecache, alltogether. but. using sessions to memcached with php5-memcached, or php5-memcache, and in php.ini set up memcache, or memcached as session save handler, phpmyadmin login is not working. any workaround for this?

[…] 刚开始不知道memcache和memcached的使用区别,配置完打开server 就报错Cannot start session without errors ……… 在网上找了找发现基本都是说目录无权限(session files存储方式)、和以前老版本phpmyadmin bug问题的(靠,难道就我不知道他俩的区别?) 后来在一个blog的评论区中找到了答案(汗一个,评论翻了好久) […]

Comments are closed.