Memcached and PHP

Memcached and PHP

data: 1 kwietnia, 2014
czas czytania: 9 min
autor: Adrian Piętka

Memcached is a highly efficient, multi-platform system for buffering the data in cache, developed by Brad Fizpatrick in 2003, for the purpose of LiveJournal service. It is mainly used to reduce the time to read from external data sources such as databases, files, and web services.

It uses client-server model, allowing running the instances of the server and the client on the same machine. We can also create the architecture of several Memcached servers and clients, in this case, however, the client must know all the servers. The programmer is also responsible for the implementation of sharding the data between them because the servers do not communicate with each other.

Particular attention should be paid to security issues connected with Memcached server – anyone can connect to it on 11211 TCP port, by doing the read and write operation. Therefore, it is a common practice to place the Memcached servers outside public access – usually in a separate private network.

Memcached is a bit like noSQL database, storing the data as an associative board: key => value. The key cannot exceed the size of 250 bytes and the stored value cannot exceed the size of 1MB.

Usage

First of all, Memcached is not suitable as a place to permanently store information. All data is stored in RAM, and when the entire buffer is filled, according to the LRU (Least Recently Used) algorithm, the least recently used items are removed. Therefore, we cannot be certain that previously saved data will be in the buffer at the time of the next reading. It is worth adding that there is a MemcacheDB project, based on Memcached assumptions, except that it permanently stores saved information.

Memcached has an API that is ready-made for the most popular programming languages, and its popularity is mainly related to the optimisation of web applications. It is often used as:

  • a place to record the user’s session – instead of using a file, as it is for example in PHP
  • a cache for:
    • part and whole-generated pages,
    • the results of SQL queries,
    • any other kind of data – i.e. boards, objects, string of characters.

Installing Memcached server for a Debian system

We can choose one of three installation methods available:

$: sudo apt-get install memcached

Running a Memcached server

After a successful installation, a Memcached Server service starts automatically – we can check it using the command:

$: ps -eaf | grep memcached

If we get a result similar to the following example, it indicates that the server is working properly:

nobody  10255  1  0 11:55 ?  00:00:00 /usr/bin/memcached -m 64 -p 11211 -u nobody -l 127.0.0.1

To be sure, it is recommended to also check the connection with Memcached. For this purpose, we’ll show the server statistics, using the application:

    • Netcat:
$: echo "stats settings" | nc localhost 11211
    • Telnet:
$: telnet localhost 11211
$: stats settings
$: quit

The result that we should obtain:

$: echo "stats settings" | nc localhost 11211
STAT maxbytes 67108864
STAT maxconns 1024
STAT tcpport 11211
STAT udpport 11211
STAT inter 127.0.0.1
STAT verbosity 0
STAT oldest 0
STAT evictions on
STAT domain_socket NULL
STAT umask 700
STAT growth_factor 1.25
STAT chunk_size 48
STAT num_threads 4
STAT num_threads_per_udp 4
STAT stat_key_prefix :
STAT detail_enabled no
STAT reqs_per_event 20
STAT cas_enabled yes
STAT tcp_backlog 1024
STAT binding_protocol auto-negotiate
STAT auth_enabled_sasl no
STAT item_size_max 1048576
STAT maxconns_fast no
STAT hashpower_init 0
STAT slab_reassign no
STAT slab_automove no
END

Of course, Memcached protocol is more comprehensive and its complete specification can be found in the documentation available on the website https://github.com/memcached/memcached/blob/master/doc/protocol.txt.

Memcached server configuration

All configuration associated with the Memcached server, in case of a Linux-associated system, is stored in the „/etc/memcached.conf” file. The most important options are:

  • -d – work mode as daemon
  • -v – verbose mode
  • -m 64 – amount of memory devoted to storing the data
  • -p 11211 – port of which the server is listening
  • -u nobody – user permissions with which the server will start
  • -l 127.0.0.1 – IP address of the server
  • -c 1024 – conncetion limit
  • logfile path – file with logs

A sample configuration file can look in the following way:

# Memcached as daemon
-d

# Log memcached's output to:
logfile /var/log/memcached.log

# Be verbose
-v

# 128 megs of RAM memory
-m 128

# Connection port is 11211
-p 11211 

# Run the daemon as nobody user
-u nobody

# Specify which IP address to listen on
-l 127.0.0.1

# Limit the number of simultaneous incoming connections
-c 2048

After the introduced changes it is required to restart the running services:

$: sudo service memcached restart

Monitoring the Memcached server

The work of the Memcached server may be the subject to monitoring, which is why few ready-made solutions were established, that differ between each other in functionality and technology, in which it was implemented. One-file PHP script – memcache.php, is a very simple solution that at the same time provides the basic information. It is worth adding that the majority of software specialising in monitoring servers like Nagios and Munin has its own extension associated with Memcached.

Memcache.php configuration is limited to the modification of the following values, placed directly in the source code:

// Username and password, required while accessing the memcache.php script
define('ADMIN_USERNAME', 'memcache');
define('ADMIN_PASSWORD', 'password');

// The definition of the list of Memcached servers
$MEMCACHE_SERVERS[] = '192.168.2.10:11211';
$MEMCACHE_SERVERS[] = '192.168.2.11:11211';

memcache

Full list of available software can be found at: http://code.google.com/p/memcached/wiki/MonitorLinks.

The use of Memcached in PHP

PHP has two built-in, object-oriented API that allow the access to the Memcached server:

  • memcache – not recommended, rather old library,
  • memcached – newer implementation, requiring additional libmemcached library, provides more features, such as:
    • APPEND/PREPEND/CAS commands,
    • We can optionally use the binary protocol.

They are available as an additional extension for PHP from PECL repository.

Memcached allows the storage of any type of variable, available in PHP (array, int, string, object, etc.), except for the typuresources variables. In case of arrays and objects, they will be stored in the serialised form. If the object has magical methods __sleep(), __wakeup(), they will be called at the appropriate moments.

  • __sleep() when saving the object,
  • __wakeup() when retrieving the object from the buffer.

Remember that the __sleep() method must return a board of object properties that will be stored in Memcached.

Installing the Memcached extension for PHP

The easiest way to install the Memcached API for PHP is via PECL:

$: sudo pecl memcached

After successful installation, make sure that the module is correctly turned on:

$: php -m | grep memcached

The final step is to restart Apache server services:

$: sudo service apache2 restart

From that moment on phpinfo() will display an additional section related to the configuration of Memcached.
memcached

Example of use

Saving the data in a Memcached session

By default, the information about the session is stored on the server as files, which causes an additional burden for the disc, because at every request incoming from the user, the data must be reloaded. Of course, the implementation of Memcached as a place for storing the session data will not be noticeable when the page is visited by only few users at a time. This makes sense only with increased traffic – then the advantage of implementing Memcached over the default way to save the session becomes greater.

The problem also occurs when you have more than one server running a copy of our application. In the standard case, each of them separately stores the session data. Implementing the Memcached can eliminate this problem by creating a focal point for the storage of such information.

In case of PHP it is enough to change two configuration directives, so that the session data are stored on the Memcached server:

session.save_handler = "memcache";
session.save_path = 'tcp://localhost:11211"

Storing objects in Memcached

First we prepare a simple class Person, consisting of three private properties firstname, surname, age, constructor and metod__sleep() and __wakeup().

class Person {

    private $firstname;
    private $surname;
    private $age;
    private $available;

    public function __construct($firstname, $surname, $age, $available)
    {
        $this->firstname = $firstname;
        $this->surname = $surname;
        $this->age = $age;
        $this->available = $available;
    }

    public function __sleep()
    {
        echo 'Sleep instance of person';
        return array('firstname', 'surname', 'age');
    }

    public function __wakeup()
    {
        echo 'Wakeup instance of person';
    }

}

Let us note that __ sleep() method returns only the name of class properties without available. When saving a Person class object in Memcached, only values for the properties firstname, surname and age will be stored.

$person = new Person('Peter', 'Smith', 30, TRUE);

$memcached = new Memcached();
$memcached->addServer('localhost', 11211);

The next step is to create a Person class object and Memcached and then to define the IP address and port of a Memcached server.

$memcached->set('person', $person);

We save the Person class object and at that time the __ sleep() method of this object is being run.

var_dump($memcached->get('person'));

Taking the value from Memcached is done by using the get() method. At the time it is being called, the __wakeup() method for Person class object will be run.

The result of the whole script should look as follows:

Sleep instance of person
Wakeup instance of person
object(Person)#3 (4) {
    ["firstname":"Person":private]=> string(5) "Peter";
    ["surname":"Person":private]=> string(5) "Smith";
    ["age":"Person":private]=> int(30)
    ["available":"Person":private]=> NULL
}

As we can see, the available value was lost. Thanks to the memcache.php tool, we can also view the data that has been stored in Memcached. The above-described object will be saved in the form of:

O:6:"Person":3:{s:28:"Personfirstname" ;s:5:"Peter";s:13:"Personsurname";s:5: "Smith";s:9:"Personage";i:30;}

Summary

Memcached is a tool of powerful capabilities. In complex, heavily loaded web applications, we were able to accelerate the generation of subpages for about few or even tens of percent. By using multiple Memcached servers, our buffer size may greatly exceed the amount of RAM, available on a single machine. Another advantage is the ease of Memcached server configuration, the documentation provided by the authors and easy-to-use API for many different programming languages.

Newsletter IT leaks

Dzielimy się inspiracjami i nowinkami z branży IT. Szanujemy Twój czas - obiecujemy nie spamować i wysyłać wiadomości raz na dwa miesiące.

Subscribe to our newsletter

Administratorem Twoich danych osobowych jest Future Processing S.A. z siedzibą w Gliwicach. Twoje dane będziemy przetwarzać w celu przesyłania cyklicznego newslettera dot. branży IT. W każdej chwili możesz się wypisać lub edytować swoje dane. Więcej informacji znajdziesz w naszej polityce prywatności.

Subscribe to our newsletter

Administratorem Twoich danych osobowych jest Future Processing S.A. z siedzibą w Gliwicach. Twoje dane będziemy przetwarzać w celu przesyłania cyklicznego newslettera dot. branży IT. W każdej chwili możesz się wypisać lub edytować swoje dane. Więcej informacji znajdziesz w naszej polityce prywatności.