Installing Memcached + PHPSo the few commands you need to launch first are to install the required software, on the 3 web servers (you can either do that on one of them then replicate the image if you are using Cloud instances, or you can install simultaneously on your 3 web servers using ClusterSSH, for example, with the cssh server1 server2 server3 command) :
sudo apt-get install memcached php5-memcached sudo service apache2 restartThe second command is to make sure Apache understands the php5-memcached extension is there. In order to enable the connection to Memcached from the different load-balanced servers, we need to change the Memcached configuration to listen on the external IP address. Check the IP address with /sbin/ifconfig. The Memcached configuration file is located in /etc/memcached.conf. Locate the "-l" option and change "127.0.0.1" for your external IP, then save and close the file. Note that this might introduce a security flaw, where you are possibly opening the connection to your Memcached server to the outside world. You can prevent that using a firewall (iptables is a big classic, available on Ubuntu) Next, restart the Memcached daemon:
sudo service memcached restartNow you have a Memcached server running on each of your web servers, accessible from the other web servers. To test this, connect to any of your web servers and try a telnet connection on the default Memcached port: 11211, like so:
user@server1$ telnet ip-server2 11211To get out of there, just type "quit" and Enter. OK, so now we have 3 Memcached servers, we only need to wrap up configuring PHP to use these Memcached servers to store sessions.
Configuring PHP to use Memcached as session storageThis is done by editing your Apache VirtualHost files (on each web server) and adding (before the closing </VirtualHost> tag) the following PHP settings:
php_admin_value session.save_handler memcached php_admin_value session.save_path "ip-server1:11211,ip-server2:11211,ip-server3:11211"Now reload your web server:
sudo service apache2 reloadYou should now be able to connect to your web application using the distributed Memcached server as a session storage (you usually don't need to change anything in your application itself, but some might exceptionally define their own session storage policy).
The dangers of using a distributed Memcached serverApart from the possible open access to your Memcached server previously mentioned, which is particularly security-related, you have to take another danger, mostly high-availability related, into account. When using a distributed Memcached server configuration, it is important to understand that it works as sharded spaces configuration. That is, it doesn't store the same sessions over on the various available Memcached server. It only stores each single session in one single server. The decision of where it will store the session is out of the context of this article, but it means that, if you have 300 users with active sessions on your system at any one time, and one of your web servers goes down, you still have 2 web servers and 2 Memcached servers, but ultimately around 100 users will loose their session (that was stored on the web server that went down). Worst: the PHP configuration will not understand this, and still try to send sessions to the server that was considered to hold these 100 sessions, making it impossible for the users to login again until the corresponding Memcached server is back up (unless you change the configuration in your PHP configuration). This is why you have to consider 2 things, and why this article is just one step in the right direction:
- you should configure the Memcached servers from inside your application for the sessions management (as such, you should have a save_handler defined inside it and check for the availability of each server *before* you store the session in it)
- if your sessions are critical, you should always have some kind of data persistence mechanism, whereby (for example), you store the session in the database once every ten times it is modified
We recently worked on that. You can find an example in the following pull requests (not yet entirely functional in the context of Chamilo, but you'll get an idea from the code, the foreach() statement, the array included, the elements checked, etc): https://github.com/chamilo/chamilo-lms/pull/344/files