¿Cómo funciona el almacenamiento en caché de objetos?

20

Estoy buscando una respuesta definitiva aquí. Cuando el almacenamiento en caché de objetos está habilitado, ¿dónde terminan viviendo las opciones y los transitorios?

Por defecto, ambos se almacenan en la base de datos. Pero he escuchado algunas referencias de que memcache las almacenará en otro lugar y APC hará algo completamente distinto. ¿Dónde, exactamente , se conservarán estos datos en ambos casos?

    
pregunta EAMann 02.12.2012 - 22:23

4 respuestas

31

WordPress, de forma predeterminada, hace una forma de "Caché de objetos", pero su vida útil es solo una carga de página.

Las opciones son realmente un buen ejemplo de esto. Echa un vistazo a esta respuesta para más información. El resumen:

  1. Se inicia una página
  2. Todas las opciones se cargan con una simple declaración SELECT option_name, option_value from $wpdb->options
  3. Las solicitudes subsiguientes para esas opciones (por ejemplo, una llamada a get_option nunca llega a la base de datos porque están almacenadas con la API de caché de WP).

Las opciones siempre "en vivo" en la base de datos y siempre se guardan allí, es su fuente "canónica". Dicho esto, las opciones se cargan en el caché de objetos, de modo que cuando solicitas una opción, existe un 99% de posibilidades de que la solicitud nunca llegue a la base de datos.

Los transitorios son un poco diferentes.

WordPress le permite reemplazar la api de caché con un drop-in , un archivo que se coloca directamente en su carpeta wp-content . Si crea su propia memoria caché o utiliza una existente plugin , puede hacer que el caché de objetos persista más tiempo que una sola carga de página. Cuando haces eso, los transitorios, cambian un poco.

Veamos la función set_transient en 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 es cierto, WordPress usa el caché de objetos en lugar de la base de datos para almacenar los transitorios. Entonces, ¿cómo se pone eso en verdadero? Es hora de explorar cómo WP configura su propia API de caché.

Puedes rastrear casi todo a wp-load.php o wp-settings.php , los cuales son cruciales para el proceso de arranque de WordPress. En nuestro caché, hay algunas líneas relevantes en wp-settings.php .

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

¿Recuerdas esa caída en la cosa desde arriba? Echemos un vistazo a wp_start_object_cache en 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' ) );
    }
}

Las líneas relevantes de la función (las que pertenecen a $_wp_using_ext_object_cache que modifican la forma en que se almacenan los transitorios).

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 en su directorio de contenido, se incluye y WP asume que está usando un caché persistente externo: establece $_wp_using_ext_object_cache en verdadero.

Si está utilizando un objeto externo, los transitorios lo usarán. Lo que hace surgir la pregunta de cuándo usar las opciones frente a las transitorias.

Simple. Si necesita que los datos persistan indefinidamente, use las opciones. Se "guardan en caché", pero sus fuentes canónicas son la base de datos y nunca desaparecerán a menos que un usuario lo solicite explícitamente.

Para los datos que deben almacenarse durante un período de tiempo establecido, pero que no es necesario que persista más allá de los transitorios de uso especificados. Internamente, WP intentará usar un caché externo de objetos persistentes si puede, de lo contrario, los datos irán a la tabla de opciones y se recogerá la basura a través de WordPress 'psuedo-cron cuando caduquen.

Algunas otras inquietudes / preguntas:

  1. ¿Está bien hacer un montón de llamadas a get_option ? Probablemente. Incurren en la llamada a una función de sobrecarga, pero es probable que no llegue a la base de datos. La carga de la base de datos a menudo es una preocupación mayor en la escalabilidad de las aplicaciones web que el trabajo que el idioma de su elección genera al generar una página.
  2. ¿Cómo sé usar transitorios frente a la API de caché? Si espera que los datos persistan durante un período determinado, use la API transitoria. Si no importa si los datos persisten (por ejemplo, no toma mucho tiempo calcular / obtener los datos, pero no debería suceder más de una vez por carga de página) use la API de caché.
  3. ¿Todas las opciones están realmente almacenadas en caché en cada carga de página? No necesariamente. Si llama a add_option con su último argumento opcional como no , no se cargarán automáticamente. Dicho esto, una vez que los recuperas, van a la memoria caché y las llamadas subsiguientes no llegan a la base de datos.
respondido por el chrisguitarguy 03.12.2012 - 06:19
5

Hay 4 tipos de caché que conozco

  1. Trivial: está siempre activado y tiene efecto antes de que entre en juego cualquier otro almacenamiento en caché. Almacena los elementos almacenados en caché en una matriz php, lo que significa que consume memoria de la sesión de ejecución de php, y que la caché se vacía después de que finaliza la ejecución de php. es decir, incluso sin utilizar ningún otro caché si llama a get_option ('opt') dos veces seguidas, realizará una consulta de base de datos solo la primera vez y la segunda vez que el valor se devolverá de la memoria.

  2. Archivo: los valores en caché se almacenan en archivos en algún lugar debajo de su directorio raíz. Creo que demostró no ser efectivo en términos de rendimiento a menos que tenga un disco muy rápido o un almacenamiento de archivos mapeado en memoria.

  3. APC (u otro almacenamiento en caché basado en el acelerador de php): los valores en caché se almacenan en la memoria de su máquina host y fuera de su asignación de memoria de php. El mayor escollo potencial es que no hay un alcance de datos y si ejecuta dos sitios, cada uno puede acceder a los datos almacenados en caché del otro, o sobrescribirlo.

  4. Memcahce: es un caché basado en la red. Puede ejecutar el servicio de almacenamiento en caché en cualquier lugar de la red y probablemente almacene los valores en su memoria de host. Probablemente no necesite memcache a menos que tenga un equilibrio de carga en acción.

Por cierto, el almacenamiento en caché de objetos es un almacenamiento en caché mucho más que opciones, almacenará casi todo lo que se recuperó de la base de datos utilizando la API de WP de alto nivel.

    
respondido por el Mark Kaplun 03.12.2012 - 06:13
0

Las opciones siempre se almacenan en la base de datos, mientras que los transitorios se pueden almacenar solo en la memoria compartida si está instalado APC y un complemento que implementa el almacenamiento en caché de APC en WP. Memcache también usa la memoria.

Las opciones también se almacenan en la memoria y se cargan desde allí cuando es posible (de lo contrario, se realiza una consulta de db).

    
respondido por el onetrickpony 03.12.2012 - 05:54
0

Gran pregunta.

Creo que aún falta la parte en la que WordPress utiliza la clase WP_Object_Cache , así que la agregaré.

De los documentos:

  

DEF: la caché de objetos de WordPress se utiliza para guardar los viajes a la base de datos. La memoria caché de objetos almacena todos los datos de la memoria caché en la memoria y hace que los contenidos de la memoria caché estén disponibles mediante el uso de una clave, que se utiliza para nombrar y posteriormente recuperar los contenidos de la memoria caché.

Aquí está la estructura WP_Object_Cache .

  

Note+espúblico,-privado,#protegido.

Utilizaelmétodostats()paramostrarestadísticasgeneralessobreelobjetodecachéglobalyloquehayallí.Aquíestálasalida:

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)

Estoesloqueobtuveantesalcomienzodeunaplantillacomosingle.php.

Notequelavariablequenosinteresaes:global$wp_object_cache.

Elprivado,elmiembro$cachetienelosdatosdealmacenamientoencachéreales.

  

Enlaprogramación,lasestructurasdecachéestánentodaspartes.Enunaformasimplesepuedenreconocercomounpardevaloresclave.Cucharones,estructurasNoDB,índicesdebasesdedatos.ElobjetivofinaldeWordPressObjectCachenoeratenerlaestructuramássimpleposible,peroaúnsepuedenreconocerparesdevaloresclave.

Desdequeestabaensingle.phpcuandoimprimíelcaché:

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

Obtendréunasolapublicaciónencaché.

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

Elobjetoseríaelvalorylaclavedealmacenamientoencachésería

get_page_by_path:2516f01e446b6c125493ec7824b63868:0.341696001481802075

Aquípuedeconsultarlaestructura$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:   }
    
respondido por el prosti 15.12.2016 - 14:53

Lea otras preguntas en las etiquetas