Collegare PHP a Valkey Sentinel, e dimostrare che il failover funziona
Una cache Valkey o Redis con Sentinel in modo che il failover arrivi davvero a PHP: tre nodi, quorum, client che interrogano Sentinel, maxmemory e un test.

Molti siti gestiscono una cache Redis o Valkey replicata e vanno comunque giù quando muore il primario, perché l'applicazione punta a un solo indirizzo fisso. Le repliche ci sono, Sentinel ne promuove una, e PHP continua a bussare alla porta del server morto. Ecco come costruire la cache in modo che il failover arrivi davvero all'applicazione, e come dimostrarlo prima di averne bisogno.
Perché la cache fa parte della vostra disponibilità
Una object cache conserva risultati calcolati: opzioni, menu, sessioni, risultati di query, frammenti renderizzati. Su un sito WordPress, Magento o Laravel trafficato assorbe la maggior parte del carico in lettura del database. Perdetela, e ogni richiesta torna tutta insieme al database. Il database non è mai stato dimensionato per quello, quindi il sito rallenta fino a trascinarsi nel giro di minuti. Una singola istanza di cache è quindi un singolo punto di guasto, anche se non contiene nulla che non possiate ricostruire.
La forma: un primario, due repliche, tre Sentinel
Eseguite tre nodi di cache su tre host separati: un primario e due repliche. Accanto a ciascuno, eseguite un processo Sentinel. I Sentinel osservano il primario, si accordano tra loro quando è sparito, promuovono una replica e rispondono alla domanda a cui ogni client ha bisogno di una risposta: dov'è il primario adesso?
Su ogni replica:
replicaof <primary-address> 6379
masterauth <secret>
requirepass <secret>
E su ciascuno dei tre Sentinel:
sentinel monitor cache <primary-address> 6379 2
sentinel auth-pass cache <secret>
sentinel down-after-milliseconds cache 5000
sentinel failover-timeout cache 30000
sentinel parallel-syncs cache 1
Il 2 nella riga monitor è il quorum: due Sentinel su tre devono concordare che il primario è giù prima che un failover inizi. Per questo ce ne sono tre, su tre host diversi.
down-after-milliseconds è il compromesso tra velocità e prudenza. Noi lo teniamo breve. Un failover non necessario costa qualche secondo di cache miss; una lunga attesa con un primario morto costa un database che si trascina.
Il passo che la gente salta: client che interrogano Sentinel
Un client configurato con l'indirizzo del primario non verrà mai a sapere di una promozione. L'applicazione deve connettersi attraverso Sentinel, per nome di servizio, e chiedere il primario corrente.
Con phpredis direttamente:
$sentinel = new RedisSentinel(['host' => '<sentinel-1>', 'port' => 26379]);
[$host, $port] = $sentinel->getMasterAddrByName('cache');
$redis = new Redis();
$redis->connect($host, (int) $port);
$redis->auth('<secret>');
Il codice di produzione dovrebbe provare ogni Sentinel a turno, dato che uno qualsiasi di loro può trovarsi sull'host appena guasto.
Per WordPress, il diffuso drop-in Redis Object Cache supporta Sentinel nativamente in wp-config.php:
define('WP_REDIS_CLIENT', 'phpredis');
define('WP_REDIS_SENTINEL', 'cache');
define('WP_REDIS_SERVERS', [
'tcp://<sentinel-1>:26379',
'tcp://<sentinel-2>:26379',
'tcp://<sentinel-3>:26379',
]);
define('WP_REDIS_PASSWORD', '<secret>');
Laravel, tramite Predis, prende una lista di Sentinel e due opzioni in config/database.php:
'redis' => [
'client' => 'predis',
'default' => [
'tcp://<sentinel-1>:26379',
'tcp://<sentinel-2>:26379',
'tcp://<sentinel-3>:26379',
'options' => ['replication' => 'sentinel', 'service' => 'cache'],
],
],
Con questo in posizione, una promozione non richiede alcuna modifica di configurazione e nessun riavvio di PHP.
Memoria: mettete un tetto e scegliete chi viene espulso
Una cache che cresce finché non interviene l'OOM killer del kernel ha fallito nel modo peggiore possibile. Impostate maxmemory a una quota fissa della RAM del nodo, lasciando spazio ai buffer di replica e al fork usato per la persistenza, e scegliete deliberatamente una policy di eviction:
- allkeys-lru per una cache pura. Quando la memoria è piena, se ne va la chiave usata meno di recente, qualunque sia. È la scelta giusta per le object cache.
- volatile-lru se l'istanza contiene anche chiavi senza scadenza che non devono mai essere espulse, come le sessioni. Sono candidate solo le chiavi con un TTL.
Meglio ancora, tenete separate sessioni e object cache. Un deploy che svuota la object cache non dovrebbe mai disconnettere tutti i clienti. Su un cluster condiviso, date a ogni sito almeno il suo database logico; ai siti grandi o critici date una loro istanza, così lo svuotamento di un sito o la crescita incontrollata delle sue chiavi non può svuotare le cache dei vicini.
Dimostratelo: spegnete il primario di proposito
Un failover che non avete osservato è una speranza. Prima della consegna, eseguiamo questo con l'applicazione connessa e il traffico in corso:
# 1. Who is primary right now?
valkey-cli -p 26379 SENTINEL get-master-addr-by-name cache
# 2. Watch the site from outside, timestamped
while true; do
printf '%s ' "$(date +%T.%N)"
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://www.example.com/
sleep 0.5
done | tee cache-failover.log
# 3. On the primary's host, stop the cache service
systemctl stop valkey
# 4. Watch the Sentinel log for +switch-master, then ask again
valkey-cli -p 26379 SENTINEL get-master-addr-by-name cache
(Con Redis, i comandi sono gli stessi sotto redis-cli.)
Annotate tre cose: quanto passa prima che compaia +switch-master, quanto passa prima che i tempi delle pagine tornino normali, e se qualche richiesta è fallita invece di rallentare soltanto. Una costruzione sana promuove in pochi secondi, e PHP segue senza che nessuno la tocchi. Poi riavviate il vecchio primario e confermate che rientra come replica del nuovo, non come secondo primario.
Per una prova più delicata che non ferma un servizio, SENTINEL FAILOVER cache forza una promozione a richiesta. Utile per testare il lato client; meno utile per testare il rilevamento, che è la parte che conta in una brutta notte.
La vostra checklist
- Tre nodi di cache e tre Sentinel su tre host separati, quorum di due.
- Autenticazione attiva, e cache raggiungibile solo dal web tier che la usa.
- Ogni applicazione che si connette attraverso Sentinel per nome di servizio, non a un indirizzo fisso.
- maxmemory impostato e una policy di eviction scelta per ciò che l'istanza contiene.
- Sessioni separate dalla object cache; siti grandi isolati da quelli piccoli.
- Un test di failover registrato con l'applicazione connessa, compreso il rientro del vecchio primario.
Se volete che colleghiamo o testiamo il vostro livello di cache, lo facciamo volentieri.
Related (rows[1])
Correlati: Object caching con failover automatico · Web tier ad alta disponibilità, N+1 a ogni livello · Costruzione di piattaforme ad alta disponibilità
Pubblicato il 18 agosto 2026.
Tutte le note dal campo