Manuel:Memcached
memcached est un objet en mémoire de type dépôt que MediaWiki peut utiliser pour mettre des valeurs en cache, afin de supprimer le temps nécessaire aux calculs très longs et pour réduire la charge des serveurs de bases de données.
Quand faut-il l'utiliser ?
Pour un petit site Web hébergé sur un seul serveur, l'installation de Memcached n'en vaut peut-être pas la peine. Dans de tels cas, envisagez de configurer MediaWiki pour utiliser l'APCu de PHP à la place comme magasin d'objets principal. Pour les grands sites Web comme Wikipedia et en général pour les wikis hébergés par plusieurs serveurs Web, Memcached est un choix courant pour le cache d'objets de MediaWiki.
Pour d'autres informations concernant les options du cache dans MediaWiki, voir le paragraphe Mise en cache des objets du manuel des performances.
Installer Memcached
La plupart des gestionnaires de packages pour Linux et macOS proposent des archives prêtes à l'emploi pour Memcached (y compris pour Debian, Fedora et Ubuntu).
Si aucune archive n'est disponible pour votre distribution, il vous faudra la compiler à partir des sources en les téléchargeant depuis [$1 memcached.org]. Pour compiler à partir des sources, libevent est nécessaire. Memcached et libevent sont des projets open source publiés sous des licences de type BSD.
Pour d'autres informations générales concernant Memcached, voir aussi Memcached sur Wikipedia.
Sécurité
Memcached n'a aucune sécurité ni authentification. Veuillez vous assurer que votre serveur est correctement protégé par un pare-feu et que le ou les ports utilisés pour les serveurs memcached ne sont pas accessibles au public. Sinon, n'importe qui sur Internet peut écrire des données et lire dans votre cache.
Un attaquant familier avec les composants internes de MediaWiki pourrait l'utiliser pour se donner un accès développeur et supprimer toutes les données de la base de données du wiki, ainsi que pour obtenir les hachages des mot de passe et les adresses courriel de tous les utilisateurs.
Client PHP pour Memcached
Au moment d'écrire ces lignes (MediaWiki 1.27), MediaWiki utilise un client memcached en PHP pur (basé sur le travail de Ryan T. Dean).
Il prend également en charge l'extension PECL php-memcached.
Pour utiliser Memcached avec MediaWiki, PHP doit être compilé avec --enable-sockets
(valeur par défaut).
If you want to use the PECL based memcached client, set $wgMainCacheType
and related cache variables to 'memcached-pecl'
instead CACHE_MEMCACHED
. The PECL memcached client supports some additional features like SASL authorization which may be useful to some users.
Pour en savoir plus sur la manière de choisir Memcached comme base arrière pour les différentes parties de MediaWiki, voir le manuel de la Mise en cache.
Configuration
Si vous voulez commencer petit, exécutez simplement une instance de memcached sur votre serveur Web :
memcached -d -l 127.0.0.1 -p 11211 -m 64
(pour fonctionner en mode daemon, accessible uniquement via l'interface loopback de bouclage, sur le port 11211, utilisant jusqu'à 64 Mo de mémoire)
Dans votre fichier LocalSettings.php, définissez :
$wgMainCacheType = CACHE_MEMCACHED;
$wgParserCacheType = CACHE_MEMCACHED; // optionnel
$wgMessageCacheType = CACHE_MEMCACHED; // optionnel
$wgMemCachedServers = [ '127.0.0.1:11211' ];
$wgSessionsInObjectCache = true; // optionnel -- supprimé en 1.33+
$wgSessionCacheType = CACHE_MEMCACHED; // optionnel
Le wiki va ensuite utiliser memcached pour mettre en cache différentes données. Pour utiliser plusieurs serveurs (machines physiquement séparées ou des caches multiples sur une machine x86 avec beaucoup de mémoire ou Power box), ajoutez simplement d'autres éléments dans ce tableau. Pour augmenter le poids d'un serveur (disons, parce qu'il a deux fois plus de mémoire que les autres et que vous voulez répartir équitablement l'utilisation), faites de son entrée un sous-tableau :
$wgMemCachedServers = [
'127.0.0.1:11211', // 1Go sur cette machine
[ '192.168.0.1:11211', 2 ] // 2Go sur cette autre machine
];
SELinux
Plusieurs règles sur Memcached existent pour les systèmes avec SELinux. Pour autoriser Apache (httpd) à accéder à Memcached, vous devez définir les règles suivantes :
setsebool -P httpd_can_network_memcache 1
Résolution des problèmes
Perte des données session lors de la sauvegarde
Si vous stockez les données session dans memcached et que les utilisateurs voient le message suivant par intermittence lorsqu'ils veulent sauvegarder leurs modifications :
Désolé, nous ne pouvons enregistrer votre modification à cause d’une perte d’informations concernant votre session.
Vous avez peut-être été déconnecté. Veuillez vérifier que vous êtes toujours connecté et réessayer. Si cela échoue de nouveau, essayez en vous déconnectant puis en vous reconnectant. Vérifiez également que votre navigateur accepte les témoins (cookies) de ce site.
cela signifie qu'un ou plusieurs de vos serveurs memcached peuvent avoir un fichier /etc/hosts
mal configuré.
Vérifiez sur chaque serveur memcached que son propre hostname vaut bien localhost:
127.0.0.1 servername.here localhost localhost.localdomain ...
Sinon le serveur ne peut pas se connecter à son propre processus memcached.
Utiliser memcached dans votre code
Si vous écrivez des extensions qui réalisent des requêtes coûteuses en temps dans la base de données, il serait utile de les mettre en cache avec memcached. Il existe plusieurs manières principales d'obtenir un gestionnaire de memcached :
- ...à utiliser si vous voulez un cache en mémoire qui soit partagé, avec des possibiltés de purge explicite afin de stocker des valeurs dérivées de sources persistentes
$cache = ObjectCache::getMainWANInstance()
- ...à utiliser si vous voulez un magasin en mémoire qui soit éphémère et non partagé avec les autres centres de données
$cache = ObjectCache::getLocalClusterInstance()
- ...à utiliser si vous voulez un cache en mémoire qui soit éphémère et non partagé avec les autres centres de données
$cache = ObjectCache::getLocalServerInstance()
- ...à utiliser si vous voulez un cache quelconque qui soit ou ne soit pas dédié à un centre de données, même si celui-ci est émulé et qu'il utilise une base de données SQL. Notez-bien que vous pouvez à la place, recevoir un gestionnaire qui communique avec Redis, APC, MySQL ou d'autres dépôts. L'utilisation du mot memcached est due historiquement à l'API définie autour des simples commandes prises en charge par memcached et au fait que aujoud'hui, memcached est normalement le meilleur magasin de caches à usage général.
$cache = wfGetCache( CACHE_ANYTHING )
Les extensions avec des besoins spécifiques (comme la persistence) doivent définir de nouveaux paramètres de configuration tels que $wgMyExtCache
ou $wgMyExtWANCache
.
Le code qui utilise les caches peut les fournir à wfGetCache()
et ObjectCache::getWANInstance()
respectivement.
L'extrait de code suivant montre comment mettre en cache les résultats d'une requête dans la base de données avec memcached pour 15 minutes mais interroge d'abord memcached pour avoir les résultats au lieu de lire la base de données.
class MyExtensionFooBars {
public function getPopularTen() {
$cache = ObjectCache::getMainWANInstance();
return $cache->getWithSetCallback(
// Les arguments variadic de wfMemcKey() sont utilisés pour construire la clé du cache de memcached.
// Elle doit être unique pour la requête que vous enregistrez.
// La première valeur est normalement le nom de l'extension ou du composant.
$cache->makeKey( 'myextension', 'foobars', 'popular', '10' ),
// en cache pour 15 minutes
$cache::TTL_MINUTE * 15,
// fonction pour générer la valeur si elle est absente du cache
function ( $oldValue, &$ttl, &$setOpts ) {
$dbr = MediaWikiServices::getInstance()->getConnectionProvider()-> getReplicaDatabase();
// ajuster TTL en fonction de la latence de réplication de la base de données
$setOpts = Database::getCacheSetOptions( $dbr );
$res = $dbr->select(
// placez ici la requête à la base de données
// voir Database::select pour la documentation
);
$data = array();
foreach ( $res as $row ) {
$data[] = array(
// Faites quelque chose avec les données recupérées de la base de données.
// Par exemple, si on cherchait un page_id dans la table 'page',
'id' => $row->page_id
);
}
return $data;
}
);
}
}
Les classes abstraites BagOStuff et WANObjectCache définissent et documentent toutes les fonctions disponibles :
Anciennes notes de développement
D'une manière générale, on a envie de placer beaucoup de données dans le cache, faites-le à chaque fois que vous pouvez et expirez-les automatiquement dès qu'il y a des modifcations de faites.
Modèle d'expiration
- délais d'expiration explicites : memcached vous permet de définir un délai d'expiration sur un objet lorsque vous le stockez. Une fois le temps écoulé, une nouvelle requête de l'objet trouve celui-ci expiré et ne renvoie rien.
- pour : repli en dernier recours pour laisser hors du cache les données qui « pourraient » être mal mises à jour
- contre : il faut connaitre d'avance le temps au bout duquel la donnée ne sera plus valide. Ce n'est pas facile quand il s'agit des modifications des utilisateurs.
- supprimer les données en cache si nous savons que nous faisons une action qui les rendra non valides et que nous sommes dans une situation qui ne permet pas de les mettre à jour
- pour : très simple ; l'élément sera rechargé à partir de la base de données et repris du cache la prochaine fois si nécessaire
- contre : si cela concerne un grand nombre d'éléments liés (par exemple, la création ou la suppression d'une page invalide les tables des liens et liens cassés ainsi que le cache des pages HTML générées qui pointent vers cette page) il faudrait tous les traiter et faire beaucoup de mises à jour
- inclure l'horadatage sur les objets en cache et gérer nos propres expirations d'après les dépendances
- pour : plusieurs objets peuvent expirer en même temps si on met à jour un noeud unique auquel ils sont rattachés
- contre : il y a davantage d'éléments à charger; les dépendances multiples peuvent devenir rapidement inextricables.
Questions et réponses
Q : Est-il possible d'utiliser une clé partielle ou une expression régulière pour la recherche avec un serveur Memcached ?
R : Non, vous ne pouvez chercher qu'avec une clé entière; si vous avez besoin d'autres informations sur ce qu'il est possible de faire, voyez le protocole Memcached
Q : Est-ce que plusieurs wikis peuvent pointer sur le même serveur Memcached ?
R : Oui, tant que les ID des wikis restent différents ($wgDBname). Certaines clés de cache sont partagées intentionnellement dans ce scénario, comme pour les limites de seuils.