Posted by & filed under Documentation, PHP.

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.

65 Responses to “Storing your PHP sessions using memcached”

  1. Alex

    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.

    Reply
  2. Guillaume Plessis

    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.

    Reply
  3. Joao Alfredo

    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.

    Reply
  4. Ruben Vandille

    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”));
    }
    }

    Reply
  5. Son

    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.

    Reply
  6. Son

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

    Reply
  7. Son

    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!

    Reply
  8. Guillaume Plessis

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

    Reply
  9. Lewis Carr

    Check that there is only 1 session save path, I had 2 in my php.ini and this caused the problem.

    Reply
  10. Laph

    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.

    Reply
  11. Lazy

    @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

    Reply
  12. bogdan

    php.ini directive should be session.save_handler = memcached NOT memcache. works ok now !

    Reply
  13. Sean

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

    Reply
  14. Laph

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

    Reply
  15. lazy

    @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

    Reply
  16. Laph

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

    Reply
  17. lazy

    @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

    Reply
  18. Laph

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

    Reply
  19. lazy

    @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

    Reply
  20. olivier

    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.

    Reply
  21. PHPGangsta

    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

    Reply
  22. feby

    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?

    Reply
  23. Chris

    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?

    Reply
  24. codef0rmer

    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?

    Reply
  25. Guillaume Plessis

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

    Reply
  26. codef0rmer

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

    Reply
  27. Guillaume Plessis

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

    Reply
  28. codef0rmer

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

    Reply
  29. codef0rmer

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

    Reply
  30. Guillaume Plessis

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

    Reply
  31. codef0rmer

    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?

    Reply
  32. Hakan

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

    Reply
  33. Bughunter

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

    Reply
  34. Stefan

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

    Reply
    • Guillaume Plessis

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

      Reply
      • Dave

        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.

        Reply
  35. Marcos

    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.

    Reply
  36. Christian

    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.

    Reply
  37. Roman

    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

    Reply
    • Alex

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

      Reply
  38. aromatherapy recipes

    At this time it looks like WordPress is the best
    blogging platform available right now. (from what I’ve read) Is that what you are using on your blog?

    Reply
  39. Rajendra

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

    Reply
  40. http://www.eassessors.com

    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!

    Reply
  41. Claus Heinrich

    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

    Reply
  42. Arun kumar

    I have 2 instances running, with one load balancer. Where should I install the memCache?

    Reply
  43. Bohuslav Jonathan Tóth

    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?

    Reply

Trackbacks/Pingbacks

  1.  JohnPuPu » Blog Archive » links for 2008-11-06
  2.  sqlite als session speicher? - Seite 2 - php.de
  3.  “Micro” Optimizations That Matter | BrandonSavage.net
  4.  “Micro” Optimizations That Matter | BrainPair - the Techno Blog
  5.  Which No-SQL DBs are recommended for storing PHP session data? - Quora
  6.  What do I change in php.ini file so that the sessions are handled in memcache? - Admins Goodies
  7.  How is session stickiness achieved across multiple web servers? - Just just easy answers
  8.  What do I change in php.ini file so that the sessions are handled in memcache? - Just just easy answers
  9.  Storing your PHP sessions using memcached | RaspberryPi Greenhouse
  10.  Learn and Use » Blog Archive » phpmyadmin session共享

Leave a Reply

  • (will not be published)


one × 5 =