È possibile utilizzare un pool di daemon memcache per condividere sessioni in modo più efficiente?


25

Stiamo passando da un'impostazione di 1 server Web a un'installazione di due server Web e devo iniziare a condividere sessioni PHP tra le due macchine con bilanciamento del carico. Abbiamo già installato memcached ( e avviato ) e quindi sono stato piacevolmente sorpreso di poter realizzare sessioni di condivisione tra i nuovi server modificando solo 3 righe nel php.inifile ( session.save_handler e session.save_path ):

Ho sostituito:

session.save_handler = files

con:

session.save_handler = memcache

Quindi sul server web principale ho impostato il session.save_pathpuntare a localhost:

session.save_path="tcp://localhost:11211"

e sul server web slave ho impostato il session.save_pathpuntamento al master:

session.save_path="tcp://192.168.0.1:11211"

Lavoro fatto, l'ho provato e funziona. Ma...

Ovviamente l'uso di memcache significa che le sessioni sono nella RAM e andranno perse se una macchina viene riavviata o il daemon memcache si arresta in modo anomalo - Sono un po 'preoccupato per questo, ma sono un po' più preoccupato per il traffico di rete tra i due server web (soprattutto come scaliamo) perché ogni volta che qualcuno è bilanciato in base al carico sul server web slave, le loro sessioni verranno recuperate attraverso la rete dal server web principale. Mi chiedevo se potevo definirne due in save_pathsmodo che le macchine guardassero nella propria memoria di sessione prima di usare la rete. Per esempio:

Maestro:

session.save_path="tcp://localhost:11211, tcp://192.168.0.2:11211"

Schiavo:

session.save_path="tcp://localhost:11211, tcp://192.168.0.1:11211"

Condividerebbe con successo le sessioni tra i server e aiuterebbe le prestazioni? vale a dire risparmiare il traffico di rete il 50% delle volte. O questa tecnica è solo per i failover (ad es. Quando un demone memcache non è raggiungibile)?

Nota : non sto davvero chiedendo in particolare la replica di memcache - più se il client memcache di PHP può raggiungere il picco all'interno di ciascun demone memcache in un pool, restituire una sessione se ne trova una e creare una nuova sessione solo se non ne trova una in tutti i negozi. Mentre scrivo, sto pensando di chiedere un po 'di più a PHP, lol ...

Supponiamo : nessuna sessione appiccicosa, bilanciamento del carico round robin, server LAMP.


1
La documentazione di Memcache non consiglia l'uso di Memcache per l'archiviazione della sessione. Vedi code.google.com/p/memcached/wiki/… !

Risposte:


37

Disclaimer: Saresti pazzo ad ascoltarmi senza fare una tonnellata di test E ottenere una seconda opinione da qualcuno qualificato - Sono nuovo di questo gioco .

L'idea di miglioramento dell'efficienza proposta in questa domanda non funzionerà. L'errore principale che ho fatto è stato pensare che l'ordine in cui i negozi memcached sono definiti nel pool impone una sorta di priorità. Questo non è il caso . Quando si definisce un pool di demoni memached (ad es. Utilizzo session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211") non è possibile sapere quale negozio verrà utilizzato. I dati sono distribuiti in modo uniforme, il che significa che un elemento potrebbe essere archiviato nel primo o potrebbe essere l'ultimo (o potrebbe essere entrambi se il client memcache è configurato per replicare - nota che è il client che gestisce la replica, il server memcached lo fa non farlo da solo). In entrambi i casi, l'utilizzo di localhost come primo nel pool non migliorerà le prestazioni: esiste una probabilità del 50% di raggiungere entrambi i negozi.

Dopo aver fatto un po 'di test e ricerche, ho concluso che PUOI condividere sessioni tra server usando memcache MA probabilmente non vorrai farlo - non sembra essere popolare perché non si ridimensiona così come usa un condiviso il database non è così robusto. Gradirei feedback su questo in modo da poter saperne di più ...

Ignora quanto segue a meno che tu non abbia un'app PHP:


Suggerimento 1: se si desidera condividere sessioni su 2 server utilizzando memcache:

Assicurati di aver risposto a " Abilitare il supporto del gestore sessioni memcache? " Quando hai installato il client memcache PHP e hai aggiunto quanto segue nel tuo /etc/php.d/memcache.inifile:

session.save_handler = memcache

Sul server web 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211"

Sul server web 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211"

Suggerimento 2: se si desidera condividere sessioni su 2 server utilizzando memcache E disporre del supporto di failover:

Aggiungi quanto segue al tuo /etc/php.d/memcache.inifile:

memcache.hash_strategy = consistent
memcache.allow_failover = 1

Sul server web 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

Sul server web 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

Gli appunti:

  • Questo evidenzia un altro errore che ho fatto nella domanda originale: non stavo usando un identico session.save_pathsu tutti i server.
  • In questo caso "failover" significa che se un demone memcache fallisce, il client memcache PHP inizierà a usare l'altro. vale a dire che chiunque abbia avuto una sessione nel negozio non riuscita verrà disconnesso. Non è un failover trasparente.

Suggerimento 3: se si desidera condividere sessioni utilizzando memcache E disporre di un supporto di failover trasparente:

Come per il suggerimento 2, tranne per il fatto che è necessario aggiungere quanto segue al /etc/php.d/memcache.inifile:

memcache.session_redundancy=2

Gli appunti:

  • Questo fa sì che il client memcache PHP scriva le sessioni su 2 server. Si ottiene ridondanza (come RAID-1) in modo che le scritture vengano inviate a n mirror e che i fallimenti get'svengano ritentati sui mirror. Ciò significa che gli utenti non perdono la sessione in caso di errore di un demone memcache.
  • Le scritture con mirroring vengono eseguite in parallelo (usando IO non bloccante), quindi le prestazioni della velocità non dovrebbero diminuire molto all'aumentare del numero di mirror. Tuttavia, il traffico di rete aumenterà se i mirror memcache sono distribuiti su macchine diverse. Ad esempio, non esiste più una probabilità del 50% di utilizzare localhost ed evitare l'accesso alla rete.
    • Apparentemente, il ritardo nella replica di scrittura può causare il recupero di vecchi dati invece di una mancanza di cache. La domanda è se questo è importante per la tua applicazione? Con quale frequenza scrivi i dati della sessione?
  • memcache.session_redundancyè per la ridondanza di sessione ma esiste anche memcache.redundancyun'opzione ini che può essere utilizzata dal codice dell'applicazione PHP se si desidera che abbia un diverso livello di ridondanza.
  • Hai bisogno di una versione recente (ancora in beta in questo momento) del client memcache PHP - La versione 3.0.3 di pecl ha funzionato per me.

Potresti commentare "non si adatta e utilizza un database condiviso"? Non vedo come sia diverso da una tipica configurazione DB master-slave. Grazie!
Boy Baukema,

Questa è una ripartizione piuttosto interessante, anche se ci sono voci (alias segnalazioni di bug) che non funzionano come previsto quando si utilizza la ext/memcacheversione 3.x. Stiamo giocando anche con questa opzione e ho deciso di scorrere l'elenco dei server e scriverlo da solo.
Fino al

nel caso del suggerimento 3: cosa succede se un host memcached si abbassa e poi si solleva, quindi l'host dei secondi si abbassa. a quanto ho capito, i dati della sessione non verranno ripristinati e alcuni di essi andranno persi, giusto?
GioMac,

28

Ri: Suggerimento 3 sopra (per chiunque si imbatta in questo tramite google), sembra che almeno al momento affinché questo funzioni, è necessario utilizzare memcache.session_redundancy = N+1per N server nel pool , almeno quella sembra essere la soglia minima valore che funziona. (Testato con php 5.3.3 su debian stable, pecl memcache 3.0.6, due server memcached. Fallirebbe session_redundancy=2non appena spegnessi il primo server in save_path, session_redundancy=3funziona bene.)

Questo sembra essere catturato in queste segnalazioni di bug:


1
Non posso votarti abbastanza ...
fest

1
Sono contento di averlo fatto scorrere verso il basso. Questo era il problema.
Daren Schwenke,

Non è chiaro per me, questa funzione è disponibile solo nella serie 3.x di PECL memcache? Tutti quelli sono elencati nel software Beta su pecl.php.net/package/memcache , mentre su 2.2.7 se uccido il server su cui vedo il leader, tutto muore.
Joe,

Sono passati anni da quando l'ho visto, a dire il vero. Come ricordo, era una funzione 3.x (icbw). Abbiamo distribuito molti sistemi utilizzando le versioni "beta" di quel plugin (alcuni dei quali con un traffico piuttosto elevato) e non abbiamo avuto problemi che sembravano correlati. YMMV, prova le cose prima che vadano in diretta, ecc. :) Non lavoro in PHP da alcuni anni ormai, quindi alcuni dei punti più fini della curiosità stanno iniziando a svanire.
Michael Jackson,

3

Insieme alle impostazioni php.ini mostrate sopra, assicurati di impostare anche le seguenti:

memcache.allow_failover = 1  
memcache.hash_strategy = 'consistent'

Quindi otterrai il failover completo e la ridondanza sul lato client. L'avvertenza con questo approccio è che se memcached è inattivo su localhost ci sarà sempre un errore di lettura prima che il client memcache php provi il server successivo nel pool specificato in session.save_path

Tieni presente che ciò influisce sulle impostazioni globali per il client php memcache in esecuzione sul tuo server web.


Usare una consistentstrategia di hashing ha senso considerando che session.save_pathè diverso su ciascun server web?
Tom,

1

memcached non funziona in questo modo (per favore correggimi se sbaglio!)

Se si desidera che l'applicazione disponga di uno spazio di archiviazione ridondante per la sessione, è necessario creare qualcosa che modifica / aggiunge / elimina le voci in entrambe le istanze memorizzate. memcached non lo gestisce, l'unica cosa che fornisce è la memorizzazione dell'hash chiave. Quindi nessuna replica, sincronizzazione, niente, nada.

Spero di non sbagliarmi su questo argomento, ma questo è ciò che so di memcached, sono passati alcuni anni da quando l'ho toccato.


Sarebbe utile per me se ti sbagli. :-) C'è un articolo in phpslacker.com ( phpslacker.com/2009/03/02/php-session-clustering-with-memcache ) che suggerisce che memcached può funzionare come descritto nella domanda. Forse dipende da come il client memcache implementa la strategia di hashing?
Tom,

1
memcache non funziona in questo modo, ma sembra che php possa funzionare nel modo desiderato. Dovrai cambiare php.ini o cambiare la tua app come descritto. Dal blog: dov'è il cluster che chiedi? Beh, a dire la verità non ce n'è. Quello che abbiamo finora è un pool memcache composto da 2 server. PHP è configurato per scrivere nel pool. PHP legge / scrive nel pool di server nell'ordine specificato dalla direttiva ini "session.save_path". Per le letture PHP richiederà un oggetto cache dalla chiave dal pool. Poiché il "failover" è abilitato, PHP interrogherà il pool di server memcache uno a uno fino al [...]
tore-

1

memcached non si replica immediatamente , ma ripubblicato (un memcached con patch) lo fa. Tuttavia, se stai già utilizzando mysql, perché non utilizzare la sua funzionalità di replica con la replica master-master e ottenere il vantaggio della replica completa dei dati.

C.


Grazie per le informazioni. Non è proprio la replica che sto cercando. È più il caso di voler raggiungere il picco in ogni memcached a turno fino a quando non viene trovata la sessione. cioè controllando localhost prima perché è più veloce e poi controllando l'altro server successivo.
Tom,

1
Nel nome di tutti gli dei PERCHÉ ???? Questa è la soluzione totalmente sbagliata a ... beh, qualsiasi problema mi venga in mente. Oltre ad essere molto inefficiente anche con solo 2 server, le prestazioni peggioreranno progressivamente molto rapidamente se si aggiungono più server. E questo non sta considerando il fatto che la tua soluzione interrompe il doppio delle probabilità rispetto a un singolo server quando in pratica l'aggiunta di server a un cluster dovrebbe ridurre la probabilità di un'interruzione. (A proposito, se vuoi dire round-robin basato su DNS, l'affinità di sessione è implicita!)
symcbean

Grazie per il feedback, sì, ammetto liberamente di essere un noob nella condivisione delle sessioni! :-) Tuttavia, non ho ancora capito perché la mia proposta sia così brutta. Ho pensato che sarebbe stato più efficiente rispetto all'utilizzo di un DB condiviso e ho anche pensato che avrebbe reso meno probabili le interruzioni.
Tom,

No, li rende più probabili. La federazione dei dati in questo modo ha senso quando si dispone di un numero molto elevato di nodi perché si riduce la quantità di replica, ma in genere si esegue una replica con un numero definito di pool per preservare la disponibilità. Dovresti essere molto esigente riguardo alle prestazioni per vedere una differenza tra la replica ripubblicata e la replica mysqld.
symcbean,

Ho testato e confermato che fintanto che sto usando allow_failover = 1, più mirror rendono le interruzioni MENO probabili. Posso spegnere un mirror, riavviarlo e spegnerlo l'altro, riavviarlo e arrestare di nuovo il primo, il tutto senza essere disconnesso. Immagino che il client memcache di PHP stia facendo molti trucchi dietro le quinte.
Tom,
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.