Vai al contenuto
EuroVPSEuroVPS

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.

Di EuroVPS Engineering

5 min di lettura
Wiring PHP to Valkey Sentinel, and proving the failover works

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.

Parla con un ingegnere

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