Devrais-je utiliser l'API transitoire pour stocker une chaîne HTML ou un objet?

18

Supposons qu’il existe un plug-in 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. Notez également que le plugin 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 .= ...;
}

Mes questions sont donc les suivantes:

  • 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 $related_posts array ou $html_output string? Si je cache $html_ouput chaîne, cela atteindra-t-il une limite maximale? Dois-je peut-être le gzip, avant de sauvegarder?
  • Devrais-je utiliser l'API transitoire du tout ici?
posée Marvin3 23.01.2016 - 17:22

3 réponses

18
  

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

Non.

Dans une version stock de WordPress, les transitoires d’installation 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 réglés sur autoload = no, ce qui ne consommera donc pas toute votre mémoire, mais il y a une autre mise en garde.

Le champ de chargement automatique dans 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, vous feriez mieux 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 de méta-post sont généralement amorcés lors de la récupération de post 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 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 des 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 sont expulsés. C’est une grande victoire pour l’approche 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 essayer très fort pour atteindre les limites de MySQL, mais par exemple, La limite d'objet est seulement de 1 Mo.

Combien de temps dure votre "logique de rendu de présentation complexe"? Exécutez-le via un profileur pour le savoir. Il y a de strongs chances que ce soit 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 donnera une requête MySQL très rapide par clé primaire.

Cela dit, si les données nécessaires par élément sont assez simples, peut-être le titre, l'URL de la vignette et le permalien, vous pouvez alors ne stocker que ces trois éléments, sans les frais généraux liés à un aller-retour supplémentaire vers MySQL, ni aux frais généraux liés à la mise en cache. très longues chaînes HTML.

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

    
réponse donnée kovshenin 25.01.2016 - 15:18
12

Tous les codes WP sont des codes publics

Si vous souhaitez publier quelque chose de public, tous les éléments kovshenin dit 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

Il est vivement recommandé de définir un cache d'objets persistants externe lorsque vous le pouvez.

Tout ce qui est dit dans la réponse de kovshenin concernant les transitoires et MySQL est tout à fait vrai. Etant 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 (petite) effort pour mettre en place un système de cache moderne comme Redis ou Memcached.

Les valeurs mises en cache peuvent ne pas exister: c'est parfait

De plus, oui, un cache d'objets externe n'est pas 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 où ils devraient être.

Le cache n'est pas le stockage, le cache est le cache.

Utiliser le cache de manière sélective

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, sur votre site privé, les performances du site peuvent améliorer considérablement , 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, dans 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 les wp_cache_* functions . Ainsi, si aucun cache externe n’est configuré, se produire en mémoire, et la base de données n’est jamais impliquée.
  • L'utilisation du cache est filtrable, pour traiter certains cas particuliers que vous pourriez rencontrer

Pas d'échelle Web 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 plutôt obligatoire .

Et bien souvent (mais pas toujours), le cache contextuel est beaucoup plus souple et plus adapté 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? Sinon, 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 1 000 utilisateurs simultanés?

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

... et constitue le 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 que vous laissiez de telles décisions aux développeurs.

... et c'est un code privé: très probablement oui . Mais même pour le code privé, la mise en cache sélective est toujours 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 nombreuses choses. Quelle est la taille de la chaîne? Quel cache externe utilisez-vous? Si vous envisagez de mettre en cache des publications, stocker l'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 à faire 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, une telle abstraction qui fonctionne immédiatement avec un ensemble de systèmes de mise en cache différents et vous permet de passer d'un système à l'autre sans effort est très difficile à trouver.

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, il ne résout pas les problèmes de code et n’est pas une solution miracle, mais un élément nécessaire pour créer un site très fréquenté qui fonctionne.

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

Vous avez juste besoin de comprendre comment les choses fonctionnent, puis de faire votre choix.

    
réponse donnée gmazzap 26.01.2016 - 21:28
2

Les réponses précédentes ont déjà mis en évidence l'obligation " Cela dépend. ", ce sur quoi je suis entièrement d'accord.

Je voudrais cependant ajouter une recommandation, basée sur la " suppose" "que 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 de l'un des avantages que ce dernier possède: Contrôle .

Comme vous devez mettre en cache les données sur une base individuelle, la quantité de données à 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 entraîner une strong affluence de visiteurs, chaque visiteur déclenchant le "code SQL trop complexe" à chaque demande de page et votre site s'enlisant complètement.

Si vous mettez les données en cache dans votre Post Meta, vous pouvez non seulement contrôler la manière 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.

N'oubliez pas que toute mise en cache est un compromis! C'est pourquoi la réponse habituelle est "ça dépend". et pourquoi il n’existe pas de "saint graal de caching".

    
réponse donnée Alain Schlesser 27.01.2016 - 12:10

Lire d'autres questions sur les étiquettes