Comment fonctionne la mise en cache des objets?

20

Je cherche une réponse définitive ici. Lorsque la mise en cache des objets est activée, où vivent les options et les transitoires?

Par défaut, les deux sont stockés dans la base de données. Mais j'ai entendu dire que memcache les stockerait ailleurs et qu'APC ferait autre chose. Où, exactement , ces données seront-elles conservées dans les deux cas?

    
posée EAMann 02.12.2012 - 22:23

4 réponses

31

WordPress utilise par défaut une forme de "Mise en cache d’objets" mais sa durée de vie n’est que le chargement d’une seule page.

Les options en sont un très bon exemple. Découvrez cette réponse . pour plus d'informations. Le résumé:

  1. Une page commence
  2. Toutes les options sont chargées avec une simple déclaration SELECT option_name, option_value from $wpdb->options
  3. Les requêtes ultérieures pour ces options (par exemple, un appel à get_option ne consultent jamais la base de données car elles sont stockées avec l'API de cache WP.

Les options sont toujours "actives" dans la base de données et y sont toujours conservées - c'est leur source "canonique". Cela dit, les options sont chargées dans le cache des objets. Ainsi, lorsque vous en demandez une, il y a 99% de chances que la demande ne parvienne jamais dans la base de données.

Les transitoires sont un peu différents.

WordPress vous permet de remplacer l’API du cache par un point d’insertion - un fichier placé directement dans votre dossier wp-content . Si vous créez votre propre cache en mémoire cache ou utilisez un existant plugin , vous pouvez faire en sorte que le cache d’objets persiste plus longtemps que le chargement d’une seule page. Lorsque vous faites cela, transitoires, changez un peu.

Examinons la fonction set_transient dans wp-includes/option.php .

<?php
/**
 * Set/update the value of a transient.
 *
 * You do not need to serialize values. If the value needs to be serialized, then
 * it will be serialized before it is set.
 *
 * @since 2.8.0
 * @package WordPress
 * @subpackage Transient
 *
 * @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
 *  transient value to be stored.
 * @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
 *
 * @param string $transient Transient name. Expected to not be SQL-escaped.
 * @param mixed $value Transient value. Expected to not be SQL-escaped.
 * @param int $expiration Time until expiration in seconds, default 0
 * @return bool False if value was not set and true if value was set.
 */
function set_transient( $transient, $value, $expiration = 0 ) {
    global $_wp_using_ext_object_cache;

    $value = apply_filters( 'pre_set_transient_' . $transient, $value );

    if ( $_wp_using_ext_object_cache ) {
        $result = wp_cache_set( $transient, $value, 'transient', $expiration );
    } else {
        $transient_timeout = '_transient_timeout_' . $transient;
        $transient = '_transient_' . $transient;
        if ( false === get_option( $transient ) ) {
            $autoload = 'yes';
            if ( $expiration ) {
                $autoload = 'no';
                add_option( $transient_timeout, time() + $expiration, '', 'no' );
            }
            $result = add_option( $transient, $value, '', $autoload );
        } else {
            if ( $expiration )
                update_option( $transient_timeout, time() + $expiration );
            $result = update_option( $transient, $value );
        }
    }
    if ( $result ) {
        do_action( 'set_transient_' . $transient );
        do_action( 'setted_transient', $transient );
    }
    return $result;
}

Hmmm $_wp_using_ext_object_cache ? Si c'est le cas, WordPress utilise le cache d'objets au lieu de la base de données pour stocker les éléments temporaires. Alors, comment est-ce que cela devient vrai? Il est temps d’explorer comment WP définit sa propre API de cache.

Vous pouvez presque tout retrouver dans wp-load.php ou wp-settings.php - ces deux éléments étant essentiels au processus d'amorçage de WordPress. Dans notre cache, il y a quelques lignes pertinentes dans wp-settings.php .

// Start the WordPress object cache, or an external object cache if the drop-in is present.
wp_start_object_cache();

Vous souvenez-vous de cette descente d’en haut? Regardons wp_start_object_cache dans wp-includes/load.php .

<?php
/**
 * Starts the WordPress object cache.
 *
 * If an object-cache.php file exists in the wp-content directory,
 * it uses that drop-in as an external object cache.
 *
 * @access private
 * @since 3.0.0
 */
function wp_start_object_cache() {
    global $_wp_using_ext_object_cache, $blog_id;

    $first_init = false;
    if ( ! function_exists( 'wp_cache_init' ) ) {
        if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
            require_once ( WP_CONTENT_DIR . '/object-cache.php' );
            $_wp_using_ext_object_cache = true;
        } else {
            require_once ( ABSPATH . WPINC . '/cache.php' );
            $_wp_using_ext_object_cache = false;
        }
        $first_init = true;
    } else if ( !$_wp_using_ext_object_cache && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
        // Sometimes advanced-cache.php can load object-cache.php before it is loaded here.
        // This breaks the function_exists check above and can result in $_wp_using_ext_object_cache
        // being set incorrectly. Double check if an external cache exists.
        $_wp_using_ext_object_cache = true;
    }

    // If cache supports reset, reset instead of init if already initialized.
    // Reset signals to the cache that global IDs have changed and it may need to update keys
    // and cleanup caches.
    if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) )
        wp_cache_switch_to_blog( $blog_id );
    else
        wp_cache_init();

    if ( function_exists( 'wp_cache_add_global_groups' ) ) {
        wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache' ) );
        wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
    }
}

Les lignes pertinentes de la fonction (celles appartenant à $_wp_using_ext_object_cache qui modifient la façon dont les transitoires sont stockés).

if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
    require_once ( WP_CONTENT_DIR . '/object-cache.php' );
    $_wp_using_ext_object_cache = true;
} else {
    require_once ( ABSPATH . WPINC . '/cache.php' );
    $_wp_using_ext_object_cache = false;
}

si object-cache.php existe dans votre répertoire de contenu, il est inclus et WP suppose que vous utilisez un cache persistant externe: il définit $_wp_using_ext_object_cache sur true.

Si vous utilisez un cache d’objets externe, les transitoires l’utiliseront. Ce qui soulève la question de savoir quand utiliser les options par rapport aux transitoires.

Simple. Si vous souhaitez que les données persistent indéfiniment, utilisez les options. Ils sont "mis en cache", mais leurs sources canoniques sont la base de données et ils ne disparaîtront jamais à moins que l'utilisateur ne le demande explicitement.

Pour les données qui doivent être stockées pendant une durée définie, mais ne doivent pas nécessairement persister au-delà d'une période transitoire d'utilisation spécifiée. En interne, WP essaiera d’utiliser un cache d’objets persistant externe s’il le peut. Sinon, les données entreront dans la table d’options et seront récupérées via Les scripts psuedo-cron de WordPress à leur date d'expiration.

Autres préoccupations / questions:

  1. Est-il possible de faire une tonne d'appels vers get_option ? Probablement. Ils encourent l'appel d'une surcharge de fonction, mais celle-ci ne sera probablement pas touchée par la base de données. La charge de la base de données est souvent un problème plus important dans l'évolutivité des applications Web que dans le travail que votre langue de choix génère pour générer une page.
  2. Comment savoir utiliser les éléments transitoires par rapport à l'API de cache? Si vous prévoyez que les données perdureront pendant une période définie, utilisez l'API transitoire. Si la persistance des données n'a pas d'importance (par exemple, le calcul / récupération des données ne prend pas longtemps, mais cela ne devrait pas se produire plus d'une fois par chargement de page), utilisez l'API de cache.
  3. Toutes les options sont-elles vraiment mises en cache sur chaque chargement de page? Pas nécessairement. Si vous appelez add_option avec son dernier argument facultatif appelé no , ils ne sont pas chargés automatiquement. Cela dit, une fois que vous les avez récupérées, elles sont placées dans le cache et les appels suivants ne parviennent pas à la base de données.
réponse donnée chrisguitarguy 03.12.2012 - 06:19
5

Il y a 4 types de cache que je connais

  1. Trivial - Il est toujours activé et prend effet avant toute autre mise en cache. Il stocke les éléments mis en cache dans un tableau php, ce qui signifie qu'il utilise la mémoire de votre session d'exécution php et que le cache est vidé une fois l'exécution de php terminée. c'est-à-dire que même sans utiliser d'autre cache, si vous appelez get_option ('opt') deux fois de suite, vous ne ferez une requête de base de données que la première fois et la seconde fois, la valeur sera renvoyée de la mémoire.

  2. Fichier - Les valeurs mises en cache sont stockées dans des fichiers quelque part dans votre répertoire racine. Je pense que cela s’est avéré inefficace en termes de performances, sauf si vous disposez d’un disque très rapide ou d’un stockage de fichiers mappé en mémoire.

  3. APC (ou autre mise en cache basée sur un accélérateur php) - Les valeurs mises en cache sont stockées dans la mémoire de votre ordinateur hôte et en dehors de votre allocation de mémoire php. Le plus grand écueil potentiel est l'absence de périmètre de données. Si vous exécutez deux sites, chacun d'entre eux peut potentiellement accéder aux données mises en cache de l'autre site ou les écraser.

  4. Memcahce - c’est un cache basé sur le réseau. Vous pouvez exécuter le service de mise en cache n'importe où sur le réseau et celui-ci stocke probablement des valeurs dans sa mémoire hôte. Vous n'avez probablement pas besoin de memcache à moins que vous n'ayez un équilibrage de charge.

BTW, la mise en cache des objets cache beaucoup plus que des options, elle stockera presque tout ce qui a été récupéré à partir de la base de données à l'aide d'une API WP de haut niveau.

    
réponse donnée Mark Kaplun 03.12.2012 - 06:13
0

Les options sont toujours stockées dans la base de données, tandis que les éléments transitoires ne peuvent l'être que dans la mémoire partagée si APC et un plug-in implémentant la mise en cache APC dans WP sont installés. Memcache utilise également la mémoire.

Les options sont également stockées en mémoire et chargées à partir de là lorsque cela est possible (sinon, une requête de base de données est effectuée).

    
réponse donnée onetrickpony 03.12.2012 - 05:54
0

Excellente question.

Je pense que la partie relative à l'utilisation de WP_Object_Cache class par WordPress est toujours manquante, je vais donc l'ajouter.

À partir de la documentation:

  

DEF: le cache d'objets WordPress est utilisé pour économiser sur les déplacements dans la base de données. Le cache d'objets stocke toutes les données du cache dans la mémoire et rend le contenu du cache disponible à l'aide d'une clé qui permet de nommer et d'extraire ultérieurement le contenu du cache.

Voici la structure WP_Object_Cache .

  

Remarque+estpublic,-privé,#protégé.

Vousutilisezlaméthodestats()pourafficherdesstatistiquesgénéralessurl'objetdecacheglobaletsursoncontenu.Voicilerésultat:

CacheHits:110CacheMisses:98Group:options-(81.03k)Group:default-(0.03k)Group:users-(0.41k)Group:userlogins-(0.03k)Group:useremail-(0.04k)Group:userslugs-(0.03k)Group:user_meta-(3.92k)Group:posts-(1.99k)Group:terms-(1.76k)Group:post_tag_relationships-(0.04k)Group:category_relationships-(0.03k)Group:post_format_relationships-(0.02k)Group:post_meta-(0.36k)

C’estcequej’avaiseuautoutdébutd’unmodèletelquesingle.php.

Notezquelavariablequinousintéresseestlasuivante:global$wp_object_cache.

Lemembreprivé$cachedétientlesdonnéesdemiseencacheréelles.

  

Enprogrammation,lesstructuresdecachesontpartout.Sousuneformesimple,ilspeuventêtrereconnuscommeunepairedevaleursdeclé.Buckets,structuresNoDB,indexdebasededonnées.LebutultimedeWordPressObjectCachen’étaitpasd’avoirlastructurelaplussimplepossible,maisdespairesdevaleurscléspouvaienttoujoursêtrereconnues.

Depuisquej'étaisdanssingle.phpquandj'aiimprimélecache:

print_r($wp_object_cache->cache['posts']);

Jereçoisunseulpostmisencache.

[last_changed]=>0.341696001481802075[get_page_by_path:2516f01e446b6c125493ec7824b63868:0.341696001481802075]=>0[2831]=>WP_PostObject([ID]=>2831[post_author]=>1...thecachedpostobjectgoeshere)

L'objetseraitlavaleuretlaclédemiseencacheserait

.
get_page_by_path:2516f01e446b6c125493ec7824b63868:0.341696001481802075

Ici,vouspouvezvérifierlastructure$cache_key:

File:/wp-includes/post.php4210:/**4211:*Retrievesapagegivenitspath.4212:*4213:*@since2.1.04214:*4215:*@globalwpdb$wpdbWordPressdatabaseabstractionobject.4216:*4217:*@paramstring$page_pathPagepath.4218:*@paramstring$outputOptional.Therequiredreturntype.OneofOBJECT,ARRAY_A,orARRAY_N,whichcorrespondto4219:*aWP_Postobject,anassociativearray,oranumericarray,respectively.DefaultOBJECT.4220:*@paramstring|array$post_typeOptional.Posttypeorarrayofposttypes.Default'page'.4221:*@returnWP_Post|array|nullWP_Post(orarray)onsuccess,ornullonfailure.4222:*/4223:functionget_page_by_path($page_path,$output=OBJECT,$post_type='page'){4224:global$wpdb;4225:4226:$last_changed=wp_cache_get_last_changed('posts');4227:4228:$hash=md5($page_path.serialize($post_type));4229:$cache_key="get_page_by_path:$hash:$last_changed";
4230:   $cached = wp_cache_get( $cache_key, 'posts' );
4231:   if ( false !== $cached ) {
4232:       // Special case: '0' is a bad '$page_path'.
4233:       if ( '0' === $cached || 0 === $cached ) {
4234:           return;
4235:       } else {
4236:           return get_post( $cached, $output );
4237:       }
4238:   }
    
réponse donnée prosti 15.12.2016 - 14:53

Lire d'autres questions sur les étiquettes