Memcache(d) to store PHP sessions
Edit: as of July 2014, there is a recent article discussing the use of php5-memcache instead of php5-memcache to store sessions on this blog.
There are many posts around on the web about using memcached to store sessions data on high-availability servers, but few actually cover the whole topic and there are some elements that I thought might be of interest in the form of a quick recap.
Memcached allows you to store frequently-used data in memory (RAM). This saves a lot of disk reads & writes and, considering disk accesses are one of the slowest elements in the software processing chain, it might vastly improve your server’s response time (your mileage may vary depending on your specific configuration). This is practical to save commonly-used variables or blocks/pages of data, but can also be used to store users sessions.
Furthermore, the system can be used to share one memcached instance between various servers, making it much easier to distribute your web servers (in high availability, redundancy and load balancing configurations), making PHP connect to the shared memcached server to save or read its session data.
Because the system in its entirety relies on available memory, and while it is acceptable to loose some data in the case of some computable data (which can be recomputed in case of lack of space in memory to store that data), it is important to note that session data must offer one of two security measures to work properly: (1) provide enough RAM space to cover all simultaneous sessions at all times or (2) provide an alternative storage system where the sessions can still be stored somewhere *out* of the available RAM space. This last point is discussed in more detail in this article.
php-memcache vs php-memcached
First of all, at the server level, we’re only talking about memcached. php-memcached is reportedly more efficient than php-memcache and overcomes some of its limitations. There is a comparison of both on the php-memcached’s Google Code page, but more importantly there are a lot of comments on the web that let you get an idea of what it’s all about. In short, php-memcached is more recent and tend to be more efficient (apparently). The second comment on a Stackoverflow question on the topic of memcache points out a series of elements that are implemented only by php-memcached.
php-memcache vs php-memcached for PHP sessions
The memcached PHP extension *probably* has a more complete implementation too.
For some reason (which I haven’t been able to figure out just yet), on a standard PHP5.2 (Ubuntu LTS 10.04) installation, the php-memcached module doesn’t really work out for handling sessions (at least the “memcached” session.save_handler doesn’t seem to be recognized), provoking response times of around 30 seconds (probably the timeout limit) which do *not* manage the session data. As such, you can still use the memcached on a server and connect to it using the php-memcache extension (use “memcache” instead of “memcached” in your session.save_handler, although I will have to check whether it is possible to use php-memcached with the “memcache” save handler). In my experience, session.save_handler=”memcached” just doesn’t work. This, however, should have been the right way, as indicated in the PHP documentation for the memcached module.
So, in my case I had two servers, one hosting the web server (184.108.40.206), another hosting the database server (220.127.116.11). Because the database server had more RAM free to use than the web server, I decided to use the database server as my memcached server, and configure my VirtualHosts to use this server. I called my servers “cpw” and “cpdb” internally (defined in /etc/hosts of each server), so my VirtualHosts included these lines:
php_value session.save_handler “memcache”
php_value session.save_path “cpdb:11211”
php_value memcache.hash_strategy “consistent”
On the database server, I installed memcached (sudo apt-get install memcached) and did the only *necessary* change in /etc/memcached.conf (the rest is up to you):
Note that this is the server’s own IP, and it is deemed dangerous to have a public IP there, as it can then be used by others as their memcached server, so you should definitely have some firewall rules in place to avoid non-personal servers to access this IP (at least through MemCache’s port 11211).
Memcached sessions handling shortcomings
The inner workings of memcached imply that any session data is in fact saved into the RAM, which also means it is highly volatile and relies highly on the RAM available on the memcached server. If your RAM space is filled with existing sessions and you need more, you will have to plan for an alternative storage resource for those sessions getting over the allowed space. This is something that is proposed in an article about memcached by Dawn Rossi. Of course, if you are looking for a quick solution to storing sessions into memcached when no more RAM is available, you can look for a file-based RDBMS or a non-SQL DB system. Memcachedb seem to be one of them.
Once you get your system setup, you might want to see how efficient it is. To do just that, download and install phpMemCacheAdmin on one of your servers. It’s pretty much downloading and uncompressing into the right web folder (standalone PHP application).
If you have a setup similar to mine above, don’t forget to go to Configuration settings and change the default 127.0.0.1 to your MemCached server’s public IP.
This is an article in constant rebuild, so please don’t hesitate to comment, I’ll include your input if useful.