Niveau :      
Résumé : memcached

Memcached, cékoidonc ? Tout d'abord c'est un mot, contrairement aux rigolos (comme moi) qui croient savoir parler anglais, on ne dit pas "memcachde" ou "mèmecachède" mais "mèmecachdi". Cette prononciation explique ce qu'est memcached : memory cache daemon, un processus qui utilise une partie de votre RAM pour en faire un cache. Le but est d'accélérer vos applications quasiment gratuitement.

Sur un site web

Ce démon a été créé pour servir de cache réparti entre plusieurs machines pour accélérer des calculs fréquents et répétitifs, comme par exemple récupérer la liste des défaites du PSG sur le site de l'Équipe. Il permet donc sur les très gros sites de réduire la charge des serveurs de base de données en mettant en RAM une bonne partie des informations.

Au lieu d'interroger directement la base de données, le site va commencer par interroger le cache et seulement ensuite la base si les informations ne se trouvent pas dans le cache (et bien sûr remplir le cache suite à ça). Ce cache fonctionne de manière distribuée, ce qui veut dire que l'information ne se trouve pas nécessairement sur la machine qui sert la page web. Plusieurs machines partagent leur mémoire et contiennent chacune une partie du cache.

Le démon

Le fonctionnement du démon est très simple : au lancement il s'alloue de la mémoire et ensuite écoute sur un port tcp les commandes qui lui sont envoyées. Celles-ci sont d'une simplicité extrême, pour simplifier, disons qu'il y en a 2 : get et set. Set permet de stocker dans la mémoire une valeur associée à une clé (exemple 199$ associé à prix_baril), get permet vous l'aurez compris de récupérer la valeur associée à une clé. L'intérêt de ces fonctions est qu'elles sont très rapides. Ajoutons pour faire plus complet une dose de timeout sur les valeurs (oui ce n'est qu'un cache), et la possibilité de supprimer ou de mettre à jour une valeur.

Cette simplicité implique qu'une certaine logique doit être implémentée au niveau du client. La bibliothèque que vous utiliserez pour communiquer avec memcached doit gérer elle même la distribution des données. La solution communément retenue est de faire un hash sur la clé et de choisir le serveur à interroger en fonction de ce hash. Le fait d'avoir le même algorithme sur tous les clients permet de garantir un fonctionnement cohérent.

Cette solution a l'avantage d'être très rapide puisque nécessitant un minimum de logique.

En pratique

En pratique, il faut une coopération sysadmin / développeur. En effet, c'est le sysadmin qui va mettre en place les cache, mais le développeur doit modifier son application pour appeler memcached et connaitre la liste des machines memcached.

Pour l'installation, je vous laisse vous faire plaisir avec votre distribution préférée. Lançons simplement memcached (en utilisateur normal, cela va de soi) :

# 1Go de ram dédié au cache par machine
<machine1>$ memcached -d -m 1024
<machine2>$ memcached -d -m 1024

Par défaut memcached écoute sur le port tcp 11211, attention il n'y a aucun contrôle d'accès, ce qui signifie que si votre machine est partagée ou si l'accès au port n'est pas filtré, toutes les informations que vous mettrez dans ce cache seront accessible (et modifiables) par des inconnus.

Maintenant il faut choisir une bibliothèque à utiliser en fonction de votre langage.

Choisissons php :

<?php

// on crée le cache et on déclare les différents serveurs
$memcache = new Memcache;
$memcache->addServer('machine1', 11211);
$memcache->addServer('machine2', 11211);

// on va chercher la données qui nous intéresse d'abord dans le cache
$value = $memcache->get('key');
if(!$value) {
  // on récupère la donnée en base
  $value = ...

  // on met à jour le cache (la valeur est valable 2minutes)
  $memcache->add('key', $value, false, 120);
}
?>

Voila, vous avez divisé par 2 la charge de votre base de données (enfin j'espère).

Remarques

Vous êtes limités sur les données à transmettre :

  • Les clés ne peuvent pas faire plus de 250 octets (attentions aux javamen qui ont des noms de variable un peu long)
  • Les données ne peuvent faire plus de 1Mo, on ne peut donc pas chacher n'importe quoi

Vous pouvez mettre les caches sur n'importe quelle machine, vous pouvez par exemple dédier un pool de machine avec beaucoup de RAM au cache. Mais dans le cas des sites web, ils consomment en général plus de CPU que de RAM, vous pouvez donc mettre les memcached directement sur les serveurs web (quitte à ajouter une barette).

Attention, le stockage des données est binaire, c'est donc le client qui les interprète, il est donc fort peu probable que vous puissiez partager des données entre différents langages à travers un memcached, en tout cas avec les bibliothèques que vous trouverez sur le net.

Vous n'êtes pas obligé d'utiliser memcached uniquement pour des sites web, toute application faisant des calculs répétitifs et ne tenant pas sur une seule machine peut avoir besoin d'un cache distribué, par exemple un moteur de recherche, un système de réservation ou toute application centralisée avec une forte audience.

Il existe 2 instructions spécifiques "incr" et "decr" permettant de gérer des compteurs sans avoir à effectuer les longs get/++/set qui pourraient de plus se retrouver en concurrenc. Mais celles-ci ne sont pas implémentées par tous les clients. Vous disposez ainsi d'un compteurs distribué entre tous vos clients. Mais temporaire car n'oubliez pas que memcached n'est qu'un cache. En tant que tel il peut disparaître, vos données ne doivent pas en pâtir, vous devez être de les récupérer (plus lentement certes) par d'autres moyens.

Cet article me semble suffisamment longs, nous verrons dans le prochain les aspects gestion et performance de memcached.