Cache des objets

This page is a translated version of the page Object cache and the translation is 100% complete.

MediaWiki utilise la mise en cache pour un grand nombre d'éléments et à différents niveaux. Cette page documente les différents caches utilisés dans l'application PHP MediaWiki.

Généralités

Il existe deux types de dépôts décrits dans le contexte des caches d'objets de MediaWiki :

  1. le cache : c'est un endroit pour ranger le résultat d'un calcul, ou des données récupérées d'une source externe (afin d'en accélérer l'accès). C'est un « cache » au sens utilisé en informatique.
  2. La zone de réserve est un endroit où l'on stocke des données en petites quantités et qui ne se trouvent pas ailleurs. Connu également comme stash (ou « magot  » d'objets). Ce sont les valeurs qu'il n'est pas possible (ou pas permis) de recalculer à la demande.

Terminologie

Une clé de cache est dite « vérifiable  » si le programme est capable de vérifier que la valeur n'est pas obsolète.

Ceci ne s'applique que si une clé possède une valeur unique, comme le calcul du 100e chiffre de Pi qui peut être mis en cache avec la clé math_pi_digit:100. Le résultat peut être rangé de manière sécurisée dans un dépôt à accès rapide sans coordination car il ne sera jamais mis à jour ni effacé. Si le contenu du cache expire, il peut être réévalué et produit le même résultat. On applique le même raisonnement pour enregistrer le wikicode d'une version (revision) donnée d'une page. La révision 123 est apparue et aura toujours le même contenu. Si le programme connait l'ID de la version cherchée, une clé de cache comme revision_content:123 peut aussi être une clé de cache vérifiable.

Enregistrement des données structurées

MediaWiki prend en charge l'enregistrement à la fois des valeurs primitives (booléens, entiers, chaînes) et des structures de tableaux (éventuellement imbriqués). Il est aussi techniquement possible d'enregistrer les objets plats (stdClass) et les instances de classes arbitraires, en s'appuyant sur la sérialisation PHP, mais ceci est obsolète pour des raisons de sécurité (T161647) et de stabilité, car il est très difficile de modifier une classe de sorte à ne pas rompre la compatibilité avant ou arrière avec les objets de cette classe se trouvant dans le cache (comme T264257, etc.).

Le code qui écrit ou qui lit dans un cache doit être à la fois compatible avant et arrière. Typiquement, les données en cache de la lecture du code ont la même valeur ou une valeur plus actuelle que le code qui les a placées dans le cache (impliquant la compatibilité arrière de la logique de lecture, ou la compatibilité avant de l'écriture anticipée), mais il existe deux scrénarii importants où le contraire est également souhaité :

  1. Pendant un déploiement, les différents serveurs et les centres de données pendant un court instant sont en train d'exécuter les anciennes versions en parallèle avec les nouvelles et la même base de données partagées avec les mêmes services de cache.

    Ainsi pendant ce temps, on peut très bien écrire dans le cache et y lire les anciennes versions et les nouvelles, de manière concurrente.

  2. Les opérateurs de sites doivent pouvoir restituer le dernier déploiement ou revenir à la précédente version du logiciel.

Bonnes pratiques :

  • Eviter de placer les constantes des versions dans les clés du cache. Utilisez le terme WANObjectCache::getWithSet avec son option version, qui gère automatiquement la compatibilité avant et arrière, et qui invalide les clés du cache en fonction des versions du logiciel.
  • Eviter d'enregistrer des objets de classes. Enregistrer des primitives ou des tableaux (imbriqués) de primitives. Les classes doivent être converties en - et à partir de - tableaux simples, et enregistrées soit comme des tableaux simples, ou comme une chaîne de caractères au format JSON. L'encodage et la sérialisation de ceux-ci doivent être faits par le consommateur et cela n'est pas fait par exemple, par les interfaces BagOStuff ou WANObjectCache. (A l'avenir, MediaWiki pourra faire cela automatiquement pour les classes implémentant JsonUnserializable, apparu avec MediaWiki 1.36).

Services

Voici les dépôts abstraits disponibles pour les fonctionnalités de MediaWiki, voir la section Utilisation pour les exemples.

Serveur local

  • Accédé via MediaWikiServices->getLocalServerObjectCache().
  • Configurable : non (détecté automatiquement).
  • Comportement : très rapide (<0.1 ms, à partir de la mémoire locale), faible capacité, non partagé entre les serveurs d'applications.

Les valeurs dans ce dépôt ne sont conservées que dans la RAM locale des serveurs web (typiquement en utilisant php-apcu). Elles ne sont pas dupliquées sur les autres serveurs ou dans les grappes, et ne possèdent pas d'options pour synchroniser la mise à jour ou l'effacement.

Si le serveur web n'a pas installé php-apcu (ou son équivalent), cette interface se replie vers un bouchon vide dans lequel aucune clé n'est stockée. Il est également initialisé sur une interface vide pour les scripts de maintenance et les autres modes en ligne de commande. MediaWiki prend en charge APCu, et WinCache.

Grappe locale (cluster)

  • Accédé via ObjectCache::getLocalClusterInstance().
  • Configurable : oui, via $wgMainCacheType.
  • Comportement : rapide (environ 1 ms, d'après le service de la mémoire), capacité moyenne, partagé entre les serveurs d'applications mais non répliqué sur les centres de données.

La plupart du temps pour usage interne seulement, pour offrir la coordination limitée des actions à l'intérieur d'un centre de données particulier. Ceci utilise le même espace de stockage serveur que le cache WAN, mais avec un espace de noms différent pour les clés, et sans aucune possibilité de diffuser les demandes de suppression aux autres centres de données.

Le cache local des grappes est typiquement sauvegardé par Memcached, mais peut aussi utiliser la base de données.

Cache WAN

  • Accédé via MediaWikiServices->getMainWANObjectCache().
  • Configurable : oui, via $wgMainWANCache, dont la valeur par défaut est $wgMainCacheType.
  • Comportement : rapide (environ 1 ms, d'après le service de la mémoire), capacité moyenne, partagé entre les serveurs d'applications, avec les événements d'invalidation répliqués sur les centres de données.

Les valeurs de ce dépôt sont rangées d'une manière centralisée dans le centre de données actuel (typiquement en utilisant Memcached en tant que base arrière). Alors que les valeurs ne sont pas répliquées sur les autres grappes, les événements de suppression (delete) et de purge des clés sont diffusés sur les autres centres de données pour l'invalidation des caches. Voir la page de référence de la classe WANObjectCache pour l'utilisation.

En résumé : calculez et rangez les valeurs via la méthode getWithSet. Pour invalider les caches, utilisez la purge des clés (et non pas l'initialisation directe de la clé).

Voir aussi WANObjectCache sur wikitech.wikimedia.org.

MicroStash

  • Accédé via MediaWikiServices->getMicroStash().
  • Configurable: oui, via $wgMicroStashType , dont la valeur par défaut est CACHE_ANYTHING.
  • Comportement : rapide (environ 1 ms d'après le service de la mémoire), capacité moyenne, partagé entre les serveurs d'applications, invalidé par le TTL. Les données stockées ne seront purgées que lorsque le TTL expirera, que les données soient utilisées ou non.

Les valeurs de ce dépôt sont stockées de manière centralisée dans les serveurs d'applications (typiquement en utilisant Memcached comme base arrière). Bien que les valeurs ne soient pas dupliquées dans d'autres centres de données, les données ne sont purgées que lorsque la durée de vie (TTL) est écoulée.

Zone de réserve principale (stash)

  • Accédé via MediaWikiServices->getMainObjectStash().
  • Configurable : oui, via $wgMainStash.
  • Comportement : peut impliquer une lecture disque (de 1 à 10 ms), semi-persistant, partagé entre les serveurs d'applications et répliqué sur les centres de données.

Les valeurs de ce dépôt sont lues et écrites dans le même centre de données, en souhaitant que les écritures soient répliquées vers d'autres centres de données mais proviennent aussi des autres données ces centres. Utilise typiquement MySQL comme base arrière. (See wikitech:MariaDB#x2 for Wikipedia's configuration.) Par défaut la table objectcache est utilisée. Il faut accepter que les lectures puissent potentiellement se bloquer, par exemple parce que les écritures dans le cache sont suspendues, ou pour des raisons de collision quand des requêtes se superposent et se terminent de manière désynchronisées, ou à cause d'écritures venant d'un autre centre de données qui aurait une latence d'une seconde pour répliquer.

Ce dépôt est supposé avoir une persistence forte et il est souvent utilisé pour les données qui ne peuvent pas être regénérées et que l'on ne retrouve pas ailleurs. Néanmoins les données stockées dans la réserve principale (Mainstash) doivent être non critiques et avoir un impact utilisateur minimal en cas de perte, permettant ainsi à la base arrière de devenir quelque fois partiellement indisponible ou effacée en cas de pression opérationnelle, sans provoquer d'incidents.

Utilisation

Enregistrement des sessions

  • Accédé via les objets Session, eux-même accédés via le SessionManager, ou RequestContext->getRequest()->getSession()
  • Configuré via $wgSessionCacheType .

Ceci n'est pas réellement un cache, dans le sens où les données sont enregistrées nulle part ailleurs.

Cache interwiki

Voir le Cache interwiki pour les détails, et aussi ClearInterwikiCache.php.

Cache de l'analyseur syntaxique

  • Accédé via la classe ParserCache.
  • La base arrière est configurée par $wgParserCacheType (typiquement MySQL).
  • Les clés sont canoniques et fonction de l'ID des pages et populées quand une page est analysée.
  • L'ID de révision est vérifié lors la récupération.

Voir le Cache de l'analyseur pour les détails. Voir également purgeParserCache.php.

Cache des messages

Texte des révisions

  • Accédé via SqlBlobStore::getBlob.
  • Enregistré dans le cache WAN en utilisant la classe de clés SqlBlobStore-blob.
  • Les clés sont vérifiables et les valeurs ne sont pas mutables. Le cache est rempli sur demande.

Contexte

Le cas d'utilisation principal de la mise en cache du texte de la version (par opposition à la recherche directe dans la table text ou le Stockage externe) sert à gérer les cas où le texte de nombreuses pages différentes est nécessaire pour une seule requête web.

Utilisé initialement par :

  • L'analyse syntaxique du wikicode. Lors de l'analyse syntaxique d'une page wiki donnée, l'analyseur (Parser) a besoin du source de la page courante, mais également et d'une manière récursive, du source de chacune des pages des modèles transclus (ainsi que des pages des modules Lua). Il n'est pas rare qu'un article populaire transclue plus de 300 telles pages. L'utilisation de Memcached permet de gagner du temps lors de la sauvegarde des modifications et de la génération de l'affichage des pages.
  • MessageCache. Ceci est une couche spécifique au wiki qui vient au-dessus du LocalisationCache et qui consiste principalement en la réécriture des messages à partir des pages de l'espace de noms « MediaWiki: » du wiki considéré. Lors de la construction de ce blob, il faut récupérer le texte source des différentes pages. Ceci est mis en cache en fonction de chaque grappe dans Memcached et localement par serveur (afin de réduire la bande passante de Memcached; r11678, commit 6d82fa2).

Exemple

Clé WANCache:v:global:SqlBlobStore-blob:<wiki>:<content address>.

content address fait référence à content.content_address de la base de données principale du wiki (par exemple tt:1123). A son tour, cela s'adresse à la table text ou au (Stockage externe).

Pour faire le reverse engineering et trouver à quelle page ou révision cela correspond, faites un Find de content.content_id pour l'adresse de contenu (SELECT content_id FROM content WHERE content_address = "tt:963546992";), puis recherchez l'ID de révision pour cet emplacement de contenu (SELECT slot_revision_id FROM slots WHERE slot_content_id = 943285896;).

L'ID de révision peut alors être utilisé sur le wiki dans une URL telle que https://en.wikipedia.org/w/index.php?oldid=951705319, ou vous pouvez le rechercher dans les tables des révisions et des pages.

Métadonnées des révisions

  • Accédé via RevisionStore::getKnownCurrentRevision.
  • Stocké dans le cache WAN en utilisant les clés de classe revision-row-1.29.
  • Les clés sont vérifiables (par page et par ID de révision) et les valeurs sont non mutables. Le cache est rempli sur demande.

MessageBlobStore

Enregistre le texte d'interface utilisé par les modules du ResourceLoader. Il est similaire au LocalisationCache, mais comprend les réécritures spécifiques au wiki. (LocalisationCache est indépendant du wiki). Ces réécritures viennent de la base de données et des pages wiki de l'espace de noms MediaWiki.

  • Accédé via MessageBlobStore.
  • Enregistré dans le cache WAN en utilisant la classe de clés MessageBlobStore.
  • Les clés sont vérifiables (à l'aide du nom du module ResourceLoader et du hachage des clés de messages). Les valeurs sont mutables et expirent après une semaine. Le cache est rempli sur demande.
  • Toutes les clés sont purgées quand on reconstruit LocalisationCache. Quand un utilisateur enregistre une modification sur une page de l'espace de noms MediaWiki du wiki, un sous-ensemble des clés est également purgé.

Cache des vignettes

ResourceLoader met en cache les versions réduites des fichiers d'entrée bruts JavaScript et CSS.

  • Accédé via ResourceLoader::filter.
  • Enregistré localement sur le serveur (APCu).
  • Les clés sont vérifiables (valeur déterministe). Pas de stratégie nécessaire pour purger. Le cache est rempli sur demande.

Cache des compilations LESS

ResourceLoader met en cache les métadonnées ainsi que les sorties de l'analyseur syntaxique des fichiers LESS qu'il a compilés.

  • Accédé via ResourceLoaderFileModule::compileLessFile.
  • Enregistré localement sur le serveur (APCu).

Hachage de l'entête du contenu des fichiers

ResourceLoader met en cache la somme de contrôle (checksum) de chaque fichier utilisé directement ou indirectement par un module. Lorsque le manifest de démarrge est distribué aux utilisateurs, les codes de hachage de plusieurs milliers de fichiers sont nécessaires. Afin de réduire la surcharge des entrées-sorties le contenu de ces hachages est placé dans le cache local et accédé via une clé formée à partir du chemin et de mtime.

  • Accédé via FileContentsHasher.
  • Enregistré localement sur le serveur (APCu).

Voir aussi