Devo usare l'API transitoria per archiviare la stringa HTML o l'oggetto?


18

Supponiamo che esista un plug-in che visualizza 20 post correlati (per ogni post) con una query molto complessa. Quindi, utilizzando i dati di questa query, crea un layout HTML complesso. Inoltre, va notato che il plug-in è pubblico e può essere installato su qualsiasi server con qualsiasi configurazione.

Qualcosa di simile a:

/* 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 .= ...;
}

Quindi le mie domande sono:

  • Qual è il modo più sicuro e più corretto per memorizzare tali dati nella cache?
  • Devo usare l'API transitoria per memorizzare nella cache $related_postsarray o $html_outputstringa? Se inserirò nella cache la $html_ouputstringa, raggiungerà un limite di dimensione massima? Dovrei forse decomprimerlo, prima di salvare?
  • Dovrei usare l'API transitoria qui?

Risposte:


18

Dovrei usare l'API transitoria qui?

No.

In uno stock di WordPress i transitori di installazione sono archiviati nella tabella wp_options e ripuliti solo durante gli aggiornamenti di base. Supponiamo di avere 50.000 post, ovvero 50.000 righe aggiuntive nella tabella delle opzioni. Ovviamente sono impostati su autoload = no, quindi non consumerà tutta la tua memoria, ma c'è un altro avvertimento.

Il campo di caricamento automatico nella tabella delle opzioni non ha un indice, il che significa che la chiamata wp_load_alloptions()a eseguirà una scansione completa della tabella. Più righe hai, più tempo ci vorrà. Più spesso scrivi nella tabella delle opzioni, meno efficienti sono le cache interne di MySQL.

Se i dati memorizzati nella cache sono direttamente correlati a un post, è meglio archiviarli nel post meta. Ciò consentirà inoltre di salvare una query ogni volta che è necessario visualizzare il contenuto memorizzato nella cache, poiché i meta-cache post vengono (di solito) innescati durante il recupero post in WP_Query.

La struttura dei dati per il meta valore può variare, è possibile disporre di un timestamp ed eseguire la query costosa se il valore memorizzato nella cache è obsoleto, proprio come si comporterebbe un transitorio.

Un altro aspetto importante da tenere presente è che i transitori di WordPress possono essere volatili in ambienti con cache degli oggetti persistente. Ciò significa che se i dati memorizzati nella cache vengono archiviati per 24 ore in un transitorio, non vi è alcuna garanzia che saranno disponibili tra 23 ore, 12 o addirittura 5 minuti. Il backend della cache degli oggetti per molte installazioni è un archivio di valori-chiave in memoria come Redis o Memcached, e se non c'è abbastanza memoria allocata per adattarsi agli oggetti più nuovi, gli oggetti più vecchi verranno sfrattati. Questa è una grande vittoria per l'approccio con meta storage.

Anche l'invalidazione può essere più intelligente, ovvero perché stai invalidando le cache dei post correlati in X ore? È perché alcuni contenuti sono cambiati? È stato aggiunto un nuovo post? È stato assegnato un nuovo tag? A seconda della "query complessa e di grandi dimensioni", è possibile scegliere di invalidare SOLO se è successo qualcosa che altererà i risultati della query.

Devo usare l'API transitoria per memorizzare nella cache l'array $ related_posts o la stringa $ html_output? Se inserirò nella cache $ html_ouput string, raggiungerà un limite di dimensione massima? Dovrei forse decomprimerlo, prima di salvare?

Dipende molto dalla dimensione della tua stringa, dal momento che sono i dati che fluiranno tra PHP, MySQL, ecc. Dovrai fare di tutto per raggiungere i limiti di MySQL, ma per esempio il limite predefinito per oggetto Memcached è solo 1 mb.

Quanto tempo impiega la tua "logica di rendering di layout complessi"? Eseguilo attraverso un profiler per scoprirlo. È probabile che sia molto veloce non diventerà mai un collo di bottiglia.

In tal caso, suggerirei di memorizzare nella cache gli ID dei post. Non gli oggetti WP_Post, perché conterranno il contenuto completo dei post, ma solo una matrice di ID post. Quindi basta usare a WP_Querycon a post__inche si tradurrà in una query MySQL molto veloce per chiave primaria.

Detto questo, se i dati necessari per articolo sono abbastanza semplici, forse titolo, url in miniatura e permalink, allora puoi archiviare solo quei tre, senza l'overhead di un ulteriore round-trip su MySQL e senza l'overhead della memorizzazione nella cache di HTML molto lungo stringhe.

Wow, ci sono molte parole, spero che ti aiuti.


12

Non tutto il codice WP è codice pubblico

Se hai intenzione di rilasciare qualcosa di pubblico, allora tutte le cose che Kovshenin ha detto sono perfettamente valide.

Le cose sono diverse se hai intenzione di scrivere codice privato per te o la tua azienda.

La cache di oggetti esterni è un grande vantaggio, in ogni caso

Se possibile, è consigliabile impostare una cache di oggetti persistenti esterni .

Tutte le cose dette nella risposta di kovshenin sui transitori e MySQL sono molto vere, e considerando che WP stesso e un gruppo di plugin fanno uso della cache degli oggetti ... quindi il miglioramento delle prestazioni ottenuto, vale assolutamente il (piccolo) sforzo di installazione un moderno sistema di cache come Redis o Memcached.

I valori memorizzati nella cache potrebbero non essere presenti: va bene

Inoltre, sì, una cache di oggetti esterna non è affidabile. Non dovresti mai fare affidamento sul fatto che c'è un transitorio. È necessario assicurarsi che funzioni, se nella cache non sono dove dovrebbero essere.

La cache non è un archivio, la cache è cache.

Usa la cache in modo selettivo

Vedi questo esempio:

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;
}

Utilizzando un codice come questo, nel tuo sito privato, le prestazioni del sito possono migliorare molto , specialmente se hai molti utenti.

Nota che:

  • Per impostazione predefinita, la cache non viene utilizzata quando il debug è attivo, quindi si spera nel proprio ambiente di sviluppo. Credetemi, la cache può rendere il debug un inferno
  • Per impostazione predefinita, la cache non viene utilizzata anche quando WP non è impostato per utilizzare una cache di oggetti esterna. Significa che non esiste tutto il problema connesso a MySQL, perché non si usa alcun transitorio quando usano MySQL. Un'alternativa probabilmente più semplice sarebbe quella di utilizzare le wp_cache_*funzioni , quindi se non è installata alcuna cache esterna, la cache si verifica in memoria e il database non è mai coinvolto.
  • L'uso della cache è filtrabile, per gestire alcuni casi limite che potresti incontrare

No Webscale If No Cache

Non dovresti provare a risolvere i problemi di velocità con la cache. Se hai problemi di velocità, dovresti ripensare al codice.

Ma per ridimensionare un sito Web su Webscale, la cache è piuttosto richiesta .

E molte volte (ma non sempre) il frammento, la cache sensibile al contesto è molto più flessibile e adatto della cache aggressiva a pagina intera.

Le tue domande:

Dovrei usare l'API transitoria qui?

Dipende .

Il tuo codice sta consumando molte risorse? Altrimenti, forse non c'è bisogno di cache. Come detto, non è solo una questione di velocità. Se il tuo codice scorre veloce ma richiede un sacco di CPU e memoria per un paio di utenti ... cosa succede quando hai 100 o 1000 utenti simultanei?

Se ti rendi conto che la cache sarebbe una buona idea ..

... ed è codice pubblico: probabilmente no . Puoi considerare di memorizzare nella cache in modo selettivo, come nel mio esempio sopra nel codice pubblico, ma di solito è meglio se lasci tali decisioni agli implementatori.

... ed è un codice privato: molto probabilmente sì . Ma anche per il codice privato, memorizzare in cache in modo selettivo è comunque una buona cosa, ad esempio per il debug.

Ricorda, comunque, che le wp_cache_*funzioni possono darti accesso alla cache senza il rischio di inquinare il database.

Devo usare l'API transitoria per memorizzare nella cache l'array $ related_posts o la stringa $ html_output?

Dipende da molte cose. Quanto sono grandi le corde? Quale cache esterna stai usando? Se hai intenzione di memorizzare nella cache i post, archiviare l'ID come array può essere una buona idea, interrogare un numero decente di post con il loro ID è abbastanza veloce.

Note finali

L'API transitoria è probabilmente una delle cose migliori di WordPress. Grazie ai plugin che puoi trovare per qualsiasi tipo di sistema cache, diventa una stupida semplice API per un gran numero di software che può funzionare sotto il cofano.

Al di fuori di WordPress, tale astrazione che funziona immediatamente con un sacco di diversi sistemi di memorizzazione nella cache e ti consente di passare da un sistema all'altro senza alcuno sforzo è molto difficile da trovare.

Raramente mi senti dire che WordPress è meglio di altre cose moderne, ma l'API transitoria è una delle poche cose che mi manca quando non lavoro con WordPress.

Sicuramente la cache è difficile, non risolve i problemi del codice e non è un proiettile d'argento, ma è qualcosa di cui hai bisogno per costruire un sito ad alto traffico che funzioni .

L'idea di WordPress di utilizzare una tabella MySQL non ottimizzata per fare cache è abbastanza folle, ma non è meglio tenersi alla larga dalla cache solo perché WordPress, per impostazione predefinita, lo fa.

Devi solo capire come funzionano le cose, quindi fare la tua scelta.


2

Le risposte precedenti hanno già messo in evidenza l'obbligo " Dipende ", al quale concordo pienamente.

Vorrei aggiungere una raccomandazione, tuttavia, in base al modo in cui " suppongo " che sarebbe meglio farlo nello scenario che stai descrivendo sopra.

Non userei i Transitori in quel caso, ma piuttosto Post Meta , a causa di un vantaggio che quest'ultimo ha: Controllo .

Poiché è necessario memorizzare nella cache i dati per post, la quantità di dati che verrà memorizzata nella cache dipende dal numero di post e crescerà nel tempo. Una volta superato un determinato numero di post, è possibile raggiungere i limiti di memoria consentiti dalla cache degli oggetti e inizierà a cancellare dalla memoria i dati precedentemente memorizzati nella cache prima della scadenza. Ciò potrebbe portare a una situazione in cui vi è un grande afflusso di visitatori, in cui ogni visitatore attiverà lo "SQL eccessivamente complesso" su ogni richiesta di pagina e il tuo sito verrà completamente impantanato.

Se si memorizzano nella cache i dati in Post Meta, non solo è possibile controllare il modo in cui vengono archiviati e recuperati, ma è anche possibile controllare esattamente come vengono aggiornati. Aggiungere un processo cron per questo che viene eseguito solo in periodi di tempo in cui il traffico sul sito è minore o assente. Pertanto, la "query lenta" non viene mai incontrata dagli utenti reali del sito e puoi persino pre-caricarla, in modo che il lavoro sia già svolto quando arriva il primo visitatore.

Tieni presente che tutta la memorizzazione nella cache è un compromesso! Ecco perché la solita risposta è "Dipende". e perché non esiste un "santo caching graal".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.