Guide

Come velocizzare WordPress con Redis Cache

In una guida precedente abbiamo visto come velocizzare WordPress con Memcached, metodo largamente utilizzato sul sito di Salvatore Aranzulla per ottenere tempi di risposta molto rapidi e poter ospitare più utenti contemporaneamente.

Oggi vedremo come utilizzare il diretto concorrente di Memcached per ottenere prestazioni ancora maggiori. Stiamo parlando di Redis, un key-value store sviluppato dal siciliano Salvatore Sanfilippo.

Molto apprezzato per le sue caratteristiche, secondo DB-Engines.com è oggi il key-value store più utilizzato al mondo. Esattamente come Memcached, su WordPress Redis è largamente utilizzato per effettuare caching di query SQL mediante il plugin Redis Object Cache.

Oggi vedremo come utilizzarlo per effettuare page caching, ovvero memorizzare in cache l’intera pagina HTML affinché questa non venga nuovamente elaborata quando richiesta una seconda volta.

A differenza del page caching effettuato da plugin come WP Super Cache, in questo caso la copia della pagina non viene memorizzata sul disco rigido bensì in memoria RAM, aumentando di gran lunga il tempo di risposta.

Installazione di Redis

Come primo passo occorre installare Redis. Su sistemi debian-based come Ubuntu, basta avviare il seguente comando che consentirà di installare sia il key-store value che il modulo per PHP:

$ sudo apt-get install redis-server php-redis

Terminata l’installazione, verificare che Redis sia installato ed attivo. Per farlo controlliamo i servizi di rete in ascolto:

$ sudo netstat -ntapd
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:443    0.0.0.0:* LISTEN 11464/nginx -g daem
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 24504/mysqld 
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 25117/redis-server 

Se tra i servizi è presente redis-server, che di default è in ascolto in localhost sulla porta 6379, allora tutto è andato a buon fine. Naturalmente come qualsiasi altro tipo di servizio è possibile stopparlo, avviarlo o riavviarlo:

$ sudo service redis-server restart

Il file di configurazione di Redis si trova di default su /etc/redis/redis.conf. Dal file di configurazione è possibile cambiare molte configurazioni tra cui la quantità di memoria RAM massima da utilizzare e la politica da adottare per rimuovere gli elementi dalla cache quando la RAM viene saturata.

La quantità massima di RAM da allocare viene specificata dalla direttiva maxmemory mentre la politica dalla direttiva maxmemory-policy:

maxmemory 500m
maxmemory-policy allkeys-lru

La quantità di memoria da allocare dipende sia dalle caratteristiche del server che dal numero di HIT della cache, per cui inizialmente le statistiche di HIT/MISS vanno monitorate per poi applicare le corrette ottimizzazioni.

Ricordarsi di riavviare il servizio ad ogni modifica del file di configurazione.

Installazione di Redis Page Cache

Il plugin Redis Page Cache può essere installato direttamente dallo stesso WordPress oppure può essere scaricato dal repository ufficiale.

Una volta installato ed attivato, copiare su wp-content il file advanced-cache.php presente all’interno della directory del plugin wp-content/plugins/pj-page-cache-red.

Dopodiché modificare wp-config.php ed inserire la seguente riga:

define('WP_CACHE', true);

Test funzionamento cache

Per controllare se la pagina viene inserita in cache, ovvero se viene effettuato un HIT anziché un MISS, occorre aprire la DevTools di Google Chrome, cliccare sul tab Network, cliccare sulla prima richiesta (ovvero la pagina web) ed andare a verificare il campo x-pj-cache-status nello header HTTP di risposta.

Pagina in cache

Pagina non in cache

Benchmark

Passiamo alla fase più interessante delle ottimizzazioni: il test delle performance. In questo caso il test è stato molto semplice. È stato misurato il Time To First Byte prima e dopo l’applicazione di Redis sullo stesso sito WordPress.

Al termine del primo test abbiamo appurato come le performance del tempo di risposta della pagina web siano aumentate del 130%!

TTFB senza Redis

TTFB con Redis

In aggiunta al primo test abbiamo effettuato anche uno stress test con loader.io di 1000 utenti in appena 60 secondi. Dai grafici sottostanti è possibile notare come senza Redis il TTFB medio sale a 855 ms mentre con Redis scende a 299 ms.

Grazie a Redis le performance sono aumentate del 186%, permettendo al server di poter gestire un numero più alto di utenti contemporaneamente connessi!

Configurazione avanzata di Redis Page Cache

Redis Page Cache non dispone di un’interfaccia grafica. Tutte le configurazioni devono essere effettuate per mezzo dell’array PHP globale $redis_page_cache_config.

Basta aprire wp-config.php ed aggiungere le righe necessarie per applicare la configurazione voluta. Ad esempio:

$redis_page_cache_config = array();

// Cambio il time to live della cache a 10 minuti (600 secondi)
$redis_page_cache_config['ttl'] = 600;

// Ignoro/elimino i seguenti cookie per migliorare la memorizzazione in cache
$redis_page_cache_config['ignore_cookies'] = array( 'wordpress_test_cookie', 'openstat_ref' );

// Per lo stesso motivo ignoro le seguenti variabili GET
$redis_page_cache_config['ignore_request_keys'] = array( 'utm_source', 'utm_medium' );

// Per le richieste mobile voglio utilizzare un contenitore di memoria differente
$redis_page_cache_config['unique'] = array( 'is_mobile' => my_is_mobile() );

È possibile effettuare altri tipi di configurazione semplicemente analizzando il contenuto del file advanced-cache.php.

Come svuotare la cache

Di default il plugin effettua il purge della cache ogni qual volta un post viene pubblicato o aggiornato, inclusa la home page ed i feeds RSS.

In ogni caso è possibile svuotare la cache manualmente creando un semplice script PHP interconnesso a WordPress (come un must use plugin). Di seguito diversi esempi di purge manuale:

// Purge per post ID
Redis_Page_Cache::clear_cache_by_post_id( $post->ID );

// Purge per URL
Redis_Page_Cache::clear_cache_by_url( 'https://example.org/secret-page/' );

// Purge per flag
Redis_Page_Cache::clear_cache_by_flag( array( 'special-flag' ) );

I flag sono come dei tag per la cache. Un post può essere rappresentato da diverse URL, ognuna avente una locazione di memoria in cache dedicata. Esempio:

https://example.org/?p=123
https://example.org/post-slug/
https://example.org/post-slug/page/2/
https://example.org/post-slug/?show_comments=1

Nell’esempio precedente è possibile vedere come il post con ID 123 può essere rappresentato da ben 4 URL. Tutte queste URL sono accomunate dall’ID 123 che viene utilizzato come flag. Se si conosce tale ID è possibile eliminare dalla cache tutte le rappresentazioni del post in una volta sola:

$post_id = 123;
$flag = sprintf( 'post:%d:%d', get_current_blog_id(), $post_id );

Redis_Page_Cache::clear_cache_by_flag( $flag );

È inoltre possibile contrassegnare i post con flag personalizzati:

// Contrassegno tutti i post con un flag che chiamo my-special-tag:
if ( is_single() && has_tag( 'my-special-tag' ) ) {
  Redis_Page_Cache::flag( 'my-special-tag' );
}

E quando si desidera svuotare la cache dei soli post basterà richiamare il metodo PHP passando come argomento il nome del flag personalizzato:

Redis_Page_Cache::clear_cache_by_flag( 'my-special-tag' );

Nota bene! Tutti i metodi di purge manuale appena discussi non eliminano gli elementi dalla memoria bensì ne azzerano il time to live affinché possano essere rimpiazzati con i nuovi. Se si desidera eliminarli dalla memoria, basterà passare al metodo un secondo argomento ($expire) da settare a false.

Redis_Page_Cache::clear_cache_by_flag( 'my-special-tag', false );

Ottimizzazione di Redis con i Socket Unix

Nella versione di default Redis utilizza i socket TCP. È possibile aumentare la velocità di circa il 25% utilizzando al loro posto i socket Unix, che operando ad un livello inferiore del modello OSI risultano essere più veloci. 

Come prima cosa aggiungere l’utente redis al gruppo www-data:

$ sudo usermod -g www-data redis

Creare la directory dove far girare il socket Unix ed attribuirgli la corretta ownership:

$ sudo mkdir -p /var/run/redis/
$ sudo chown -R redis:www-data /var/run/redis

Dopodiché aprire il file di configurazione di Redis ed aggiungere le seguenti righe:

unixsocket /var/run/redis/redis.sock
unixsocketperm 775

Salvare il file e riavviare Redis:

$ sudo service redis-server restart

A questo punto verificare l’avvenuta creazione del descrittore del socket Unix all’interno di /var/run/redis/:

$ ls /var/run/redis/
redis.sock

Una volta sicuri che il socket unix sia stato creato correttamente, modificare wp-config.php e aggiungere la seguente configurazione di Redis Page Cache per specificare il path del socket unix:

$redis_page_cache_config = array();
$redis_page_cache_config['redis_host'] = '/var/run/redis/redis.sock';

Salvare e verificare il corretto funzionamento della cache.

Conclusione

Abbiamo visto come utilizzare Redis come cache HTML per le pagine del nostro sito WordPress. Così come per Memcached ed Nginx FastCGI Cache, questa configurazione di Redis non permette di memorizzare in RAM anche una copia dei file statici, come immagini e fogli di stile.

Tale limitazione ci consente dunque di sopperire alla “sola” elaborazione PHP della pagina. Successivamente vedremo come installare sul server uno stack con Varnish per effettuare anche caching di file statici, memorizzando in RAM una copia completa del sito web.

Per ottenere tempi di caricamento prossimi al secondo per siti web complessi come WordPress, non basta solo curare gli aspetti lato server. L’applicazione web va infatti ottimizzata nel suo percorso di rendering critico affinché il browser, special modo se mobile, riesca a velocizzarne la visualizzazione.

Se anche tu vuoi ottenere la massima velocità dal tuo sito web continua a seguire le guide su questo sito o richiedi una consulenza in performance.

Salvatore Fresta

Disqus Comments Loading...
Share
Pubblicato da
Salvatore Fresta
Tag: wordpress

Recent Posts

Cloudflare: come identificare la location del server

Cloudflare si antepone tra il server di origine e la richiesta dell'utente per servire file…

18 Marzo 2019

Ottimizzazione MySQL: come scegliere il valore di InnoDB Buffer Pool

L'ottimizzazione del database MySQL è tra i tuning più importanti in tema di performance web.…

5 Marzo 2019

Cache di post e pagine WordPress con Cloudflare

Cloudflare è un ottimo servizio utilizzato sia per migliorare le performance in caso di traffico…

19 Settembre 2018

WordPress, CDN, offloading e compressione immagini

Una delle tante pratiche di ottimizzazione del tempo di caricamento pagina quando si riceve un…

22 Maggio 2018

WordPress e WebP: guida completa

WebP è un formato di immagine sviluppato da Google ed appositamente pensato per ottimizzare il…

17 Maggio 2018

Caching avanzato con i Service Worker

Qualche settimana fa abbiamo visto cosa sono i service worker e come utilizzarli per creare…

12 Maggio 2018