web-dev-qa-db-fra.com

Devrais-je utiliser l'API transitoire pour stocker des chaînes HTML ou des objets?

Supposons qu’il existe un plugin qui affiche 20 messages liés (pour chaque message) avec une requête très complexe. Et puis en utilisant les données de cette requête, il construit une mise en page HTML complexe. En outre, il convient de noter que le plug-in est public et peut être installé sur n'importe quel serveur avec n'importe quelle configuration.

Quelque chose comme:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = '';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */   
     $html_output .= ...;
}

Donc mes questions sont:

  • Quel est le moyen le plus sûr et le plus correct de mettre en cache de telles données?
  • Devrais-je utiliser l'API transitoire pour mettre en cache le tableau $related_posts ou la chaîne $html_output? Si je cache la chaîne $html_ouput, atteindra-t-elle une limite de taille maximale? Dois-je peut-être le gzip, avant de sauvegarder?
  • Devrais-je utiliser l'API transitoire du tout ici?
18
Marvin3

Devrais-je utiliser l'API transitoire du tout ici?

Non.

Dans le stock, les transitoires d'installation de WordPress sont stockés dans la table wp_options et ne sont nettoyés que lors des mises à niveau principales. Supposons que vous avez 50 000 articles, soit 50 000 lignes supplémentaires dans la table des options. De toute évidence, ils sont configurés pour charger automatiquement = non, donc cela ne va pas utiliser toute votre mémoire, mais il y a une autre mise en garde.

Le champ autoload de la table d'options n'a pas d'index, ce qui signifie que l'appel à wp_load_alloptions() va effectuer une analyse complète de la table. Plus vous avez de lignes, plus cela prendra de temps. Plus vous écrivez souvent dans la table d'options, moins les caches internes de MySQL sont efficaces.

Si les données en cache sont directement liées à une publication, il est préférable de les stocker dans la méta de publication. Cela vous évitera également une requête à chaque fois que vous aurez besoin d'afficher le contenu mis en cache, car les caches meta-caches sont (généralement) amorcés lors de la récupération de la publication dans WP_Query.

Votre structure de données pour la méta-valeur peut varier, vous pouvez avoir un horodatage et exécuter votre requête coûteuse si la valeur mise en cache est obsolète, un peu comme le ferait un passager.

Une autre pensée importante à garder à l'esprit est que les transitoires de WordPress peuvent être volatils dans les environnements avec la mise en cache d'objets persistante. Cela signifie que si vous stockez vos données en cache pendant 24 heures dans un environnement transitoire, rien ne garantit qu'elles seront disponibles dans 23 heures, ou même 12, voire 5 minutes. Le backend du cache des objets pour de nombreuses installations est un magasin clé-valeur en mémoire, tel que Redis ou Memcached, et s'il n'y a pas assez de mémoire allouée pour les nouveaux objets, les anciens éléments seront expulsés. C'est une victoire énorme pour l'approche de méta-stockage.

L’invalidation peut aussi être plus intelligente, c’est-à-dire pourquoi invalidez-vous les caches de messages liés en X heures? Est-ce parce que certains contenus ont changé? Un nouveau message a été ajouté? Une nouvelle balise a été attribuée? En fonction de votre "requête complexe et volumineuse", vous pouvez choisir d'invalider UNIQUEMENT si quelque chose est sur le point de modifier les résultats de votre requête.

Devrais-je utiliser l'API transitoire pour mettre en cache le tableau $ related_posts ou la chaîne $ html_output? Si je cache la chaîne $ html_ouput, atteindra-t-elle une limite de taille maximale? Dois-je peut-être le gzip, avant de sauvegarder?

Cela dépend beaucoup de la taille de votre chaîne, car ce sont les données qui vont circuler entre PHP, MySQL, etc. Vous devrez faire de votre mieux pour atteindre les limites de MySQL, mais par exemple, la limite par objet par défaut de Memcached est seulement 1 mb.

Combien de temps dure votre "logique de rendu de mise en page complexe"? Exécutez-le via un profileur pour le savoir. Les chances sont que c'est très rapide ne deviendra jamais un goulot d'étranglement.

Si tel est le cas, je suggérerais de mettre en cache les identifiants de publication. Pas les objets WP_Post, car ceux-ci contiendront le contenu complet de la publication, mais simplement un tableau d'ID de publication. Ensuite, utilisez simplement un WP_Query avec un post__in, ce qui entraînera une requête MySQL très rapide par clé primaire.

Cela dit, si les données nécessaires par élément sont assez simples (titre, URL miniature et permalien, par exemple), vous ne pouvez stocker que ces trois éléments, sans la charge supplémentaire nécessaire à l’aller-retour vers MySQL ni la surcharge liée à la mise en cache de très longs codes HTML. des cordes.

Wow c'est beaucoup de mots, j'espère que ça aide.

18
kovshenin

Pas tout WP Code est un code public

Si vous voulez publier quelque chose de public, alors toutes les choses kovshenin dites sont parfaitement valables.

Les choses sont différentes si vous écrivez un code privé pour vous-même ou votre entreprise.

Le cache d'objets externe est un avantage considérable, dans tous les cas

Pour définir un cache d'objets persistants externe, il est très recommandé , lorsque vous le pouvez.

Tout ce qui est dit dans la réponse de kovshenin à propos des transitoires et de MySQL est très vrai, et étant donné que WP lui-même et un tas de plugins utilisent le cache d'objets ... alors l'amélioration des performances que vous avez obtenue vaut vraiment la (petit) effort pour installer un système de cache moderne comme Redis ou Memcached.

Les valeurs en cache peuvent ne pas être là: c'est très bien

De plus, oui, un cache d'objets externe est not fiable. Vous ne devriez jamais compter sur le fait qu'il y a un transitoire. Vous devez vous assurer que cela fonctionne si les éléments en cache ne sont pas là où ils se trouvent {devrait} _.

Cache n'est pas stockage, cache est cache.

Utiliser le cache sélectivement

Voir cet exemple:

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined('WP_DEBUG') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters('my_use_cache', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}

En utilisant un code comme celui-ci, dans votre site privé, les performances du site peuvent améliorer beaucoup , en particulier si vous avez beaucoup d'utilisateurs.

Notez que:

  • Par défaut, le cache n'est pas utilisé lorsque le débogage est activé, donc espérons-le sur votre environnement de développement. Croyez-moi, le cache peut faire du débogage un enfer
  • Par défaut, le cache n'est pas non plus utilisé lorsque WP n'est pas configuré pour utiliser un cache d'objets externe. Cela signifie que tout le problème lié à MySQL n'existe pas, car vous n'utilisez aucun transitoire quand ils utilisent MySQL. Une alternative probablement plus simple consisterait à utiliser wp_cache_* fonctions . Ainsi, si aucun cache externe n’est configuré, le cache se produit en mémoire et la base de données n’est jamais impliquée.
  • L'utilisation du cache est filtrable, pour traiter certains cas Edge que vous pouvez rencontrer

Pas de Webscale si pas de cache

Vous ne devez pas essayer de résoudre les problèmes de vitesse avec le cache. Si vous avez des problèmes de vitesse, vous devriez alors repenser votre code.

Mais pour redimensionner un site Web à l'échelle Web, le cache est joli required .

Et souvent, le cache contextuel fragmenté (mais pas toujours) est beaucoup plus souple et convient que le cache agressif de pages complètes.

Vos questions:

Devrais-je utiliser l'API transitoire du tout ici?

Cela dépend .

Votre code consomme-t-il beaucoup de ressources? Si non, peut-être qu'il n'y a pas besoin de cache. Comme dit, ce n’est pas seulement une question de vitesse. Si votre code est rapide mais qu'il nécessite beaucoup de ressources processeur et de mémoire pour quelques utilisateurs, que se passe-t-il lorsque vous avez 100 ou 1000 utilisateurs simultanés?

Si vous réalisez que cache serait une bonne idée ..

... et est un code public: probablement pas . Vous pouvez envisager de mettre en cache de manière sélective, comme dans l'exemple ci-dessus dans le code public, mais il est généralement préférable de laisser de telles décisions aux développeurs.

... et est un code privé: très probablement oui . Mais même pour le code privé, la mise en cache sélective reste une bonne chose, par exemple pour le débogage.

N'oubliez pas que les fonctions wp_cache_* peuvent vous donner accès au cache sans risque de pollution de la base de données.

Devrais-je utiliser l'API transitoire pour mettre en cache le tableau $ related_posts ou la chaîne $ html_output?

Cela dépend de beaucoup de choses. Quelle est la taille de la chaîne? Quel cache externe utilisez-vous? Si vous envisagez de mettre en cache des publications, stocker ID en tant que tableau peut être une bonne idée, interroger un nombre correct de publications par leur ID est assez rapide.

Notes finales

L'API transitoire est probablement l'une des meilleures choses de WordPress. Grâce aux plugins que vous pouvez trouver pour tous les types de systèmes de cache, il devient une simple API stupide pour un grand nombre de logiciels pouvant fonctionner sous le capot.

En dehors de WordPress, il est très difficile de trouver une telle abstraction qui fonctionne immédiatement avec un tas de systèmes de mise en cache différents et vous permet de passer d'un système à un autre sans effort.

Vous m'entendez rarement dire que WordPress est meilleur que les autres logiciels modernes, mais l'API transitoire est l'une des rares choses qui me manque lorsque je ne travaille pas avec WordPress.

Bien sûr, le cache est difficile, ne résout pas les problèmes de code et n’est pas une solution miracle, mais c’est quelque chose dont vous avez besoin pour créer un site très fréquenté qui fonctionne.

L'idée de WordPress d'utiliser une table sous-optimisée de MySQL pour faire du cache est assez folle, mais il n'est pas préférable de se garder du cache simplement parce que WordPress le fait par défaut.

Vous devez juste comprendre comment les choses fonctionnent, puis faites votre choix.

12
gmazzap

Les réponses précédentes ont déjà souligné le caractère obligatoire " Cela dépend. ", ce sur quoi je suis tout à fait d'accord.

Je voudrais cependant ajouter une recommandation basée sur la façon dont " suppose " cela serait mieux réalisé dans le scénario que vous décrivez ci-dessus.

Je ne voudrais pas utiliser Transitoires dans ce cas, mais plutôt Post Meta , en raison d'un avantage que ce dernier a: Contrôle .

Comme vous devez mettre en cache les données sur une base individuelle, la quantité de données que vous allez mettre en cache dépend du nombre de publications et augmentera avec le temps. Une fois que vous avez dépassé un certain nombre de publications, vous pouvez atteindre les limites de la mémoire que votre cache d’objets est autorisé à utiliser et il commencera à effacer de la mémoire les données précédemment mises en cache avant leur expiration. Cela pourrait conduire à une situation où vous avez un afflux important de visiteurs, où chaque visiteur déclenchera le "code SQL trop complexe" à chaque demande de page et votre site s'enlisera complètement.

Si vous mettez les données en cache dans votre publication Meta, vous pouvez non seulement contrôler la façon dont elles sont stockées et récupérées, mais également contrôler exactement la façon dont elles sont mises à jour. Vous ajouteriez pour cela une tâche cron qui s'exécute uniquement aux périodes où le trafic sur le site est faible, voire inexistant. Ainsi, la "requête lente" n'est jamais rencontrée par les utilisateurs réels du site et vous pouvez même la précharger au préalable, de sorte que le travail soit déjà effectué lorsque le premier visiteur accède.

Gardez à l'esprit que toute mise en cache est un compromis! C'est pourquoi la réponse habituelle est "ça dépend". et pourquoi il n'y a pas de "saint graal caching".

2
Alain Schlesser