2013-05-16 33 views
6

Desidera sincronizzare i dati della cache tra due server. Entrambi i database condividono lo stesso database, ma per dati di esecuzione migliori ho memorizzato i dati in Hash Map all'avvio. Pertanto, desidera sincronizzare i dati memorizzati nella cache senza riavviare i server. (Entrambi i server si avviano alla stessa ora).Il modo migliore per sincronizzare i dati della cache tra due server

Si prega di suggerire il modo migliore ed efficace per fare.

risposta

22

Invece di provare a sincronizzare i dati memorizzati nella cache tra due istanze del server, perché non centralizzare la memorizzazione nella cache invece di utilizzare qualcosa come memcached/couchbase o redis? L'utilizzo della cache distribuita con qualcosa come ehcache è molto più complicato e IMO incline agli errori, e centralizza i dati memorizzati nella cache utilizzando un server di caching come quelli menzionati.

Come addendum alla mia risposta originale, al momento di decidere quale approccio di caching utilizzare (in memoria, centralizzato), una cosa da tenere in considerazione è la volatilità dei dati che vengono memorizzati nella cache.

Se i dati sono memorizzati nel DB, ma non cambiano dopo che i server lo hanno caricato, non è nemmeno necessario sincronizzare i server. Lascia che ognuno carichi questi dati statici in memoria dalla sorgente e poi si metta in giro per i loro modi allegri facendo qualunque cosa essi facciano. I dati non cambieranno, quindi non è necessario introdurre un modello complicato per mantenere i dati sincronizzati tra i server.

Se esiste effettivamente un livello di volatilità nei dati (come dire che si sta memorizzando nella cache i dati delle entità dal DB per salvare gli accessi al DB), allora penso ancora che il caching centralizzato sia un approccio migliore rispetto a -memoria distribuita e cache sincronizzata. Devi solo assicurarti di utilizzare una scadenza appropriata sui dati memorizzati nella cache per consentire il naturale aggiornamento dei dati di volta in volta. Inoltre, potresti voler semplicemente eliminare i dati memorizzati nella cache dall'archivio centralizzato quando ci si trova nel percorso di aggiornamento per una determinata entità e quindi lasciarlo ricaricare dalla cache alla richiesta successiva per quei dati. Questo è IMO migliore rispetto al tentativo di creare una vera cache write-through in cui si scrive nell'archivio sottostante e nella cache. Il DB stesso potrebbe apportare modifiche ai dati (ad esempio, per impostazione predefinita, valori non forniti) e i dati memorizzati nella cache in quel caso potrebbero non corrispondere a quelli presenti nel DB.

EDIT:

Una domanda è stato chiesto nei commenti circa i vantaggi di una cache centralizzata (sto cercando di indovinare contro qualcosa come un in memoria cache distribuita). Fornirò la mia opinione al riguardo, ma prima un disclaimer standard. Il caching centralizzato non è un toccasana. Mira a risolvere problemi specifici relativi alla cache in-jvm-memory. Prima di valutare se passare o meno ad esso, dovresti capire quali sono i tuoi problemi per primi e vedere se si adattano ai vantaggi del caching centralizzato. Il caching centralizzato è un cambiamento architettonico e può venire con problemi/caveat a sé stante. Non passare ad esso semplice perché qualcuno dice che è meglio di quello che stai facendo. Assicurati che la ragione si adatti al problema.

Ok, ora a mio parere per quali tipi di problemi il caching centralizzato può risolvere in caching in-jvm-memory (e possibilmente distribuito). Ho intenzione di elencare due cose, anche se sono sicuro che ce ne sono altre. I miei due grandi sono: Impronta memoria totale e Problemi di sincronizzazione dei dati.

Iniziamo con Ingombro di memoria complessivo. Supponiamo che tu stia facendo il caching di entità standard per proteggere il tuo DB relazionale dallo stress eccessivo. Diciamo anche che hai un sacco di dati da memorizzare nella cache per proteggere davvero il tuo DB; diciamo nel raggio di molti GB.Se si sta facendo il caching in-jvm-memory e si dice che aveva 10 caselle del server delle app, è necessario ottenere quella memoria aggiuntiva ($$$) volte 10 per ciascuna delle caselle che avrebbero bisogno di fare la memorizzazione nella cache in jvm memoria. Inoltre, sarà necessario allocare un heap più grande alla JVM per poter ospitare i dati memorizzati nella cache. Sono dell'opinione che l'heap JVM dovrebbe essere piccolo e snello per facilitare il carico di raccolta dei rifiuti. Se hai una grossa porzione di Old Gen che non può essere raccolta, devi stressare il tuo garbage collector quando entra in un GC completo e cerca di raccogliere qualcosa da quel gonfioso spazio della Vecchia Gen. Vuoi evitare lunghi tempi di pausa GC2 e gonfiore, la tua Vecchia Gen non ti aiuterà in questo. Inoltre, se il requisito di memoria è superiore a una determinata soglia e hai installato macchine a 32 bit per il tuo livello di app, dovrai eseguire l'upgrade a macchine a 64 bit e questo può essere un altro costo proibitivo.

Ora, se si decidesse di centralizzare i dati memorizzati nella cache (usando qualcosa come Redis o Memcached), si potrebbe ridurre in modo significativo l'ingombro di memoria complessivo dei dati memorizzati nella cache, poiché si potrebbe avere su un paio di caselle invece di tutte caselle del server delle app nel livello dell'app. Probabilmente vorresti usare un approccio cluster (entrambe le tecnologie lo supportano) e almeno due server per darti una disponibilità elevata ed evitare un singolo punto di errore nel tuo livello di cache (di più su questo in un secondo). Con uno che ha un paio di macchine per supportare i requisiti di memoria necessari per la memorizzazione nella cache, è possibile risparmiare alcuni notevoli $$. Inoltre, puoi ora regolare le caselle delle app e le caselle della cache in modo diverso poiché servono a scopi diversi. Le caselle delle app possono essere ottimizzate per un throughput elevato e un heap basso e le caselle della cache possono essere ottimizzate per la memoria di grandi dimensioni. E avere un minor numero di heap ti aiuterà sicuramente con il throughput complessivo delle caselle del livello dell'app.

Ora un punto rapido per il caching centralizzato in generale. Dovresti configurare la tua applicazione in modo che possa sopravvivere senza la cache nel caso in cui vada giù per un periodo di tempo. Nel tradizionale caching delle entità, ciò significa che quando la cache diventa completamente non disponibile, si sta colpendo direttamente il DB per ogni richiesta. Non eccezionale, ma non anche la fine del mondo.

Ok, ora per Problemi di sincronizzazione dei dati. Con il caching in-jvm-memory distribuito, è necessario mantenere la cache sincronizzata. Una modifica ai dati memorizzati nella cache in un nodo deve essere replicata negli altri nodi e sincronizzata nei dati memorizzati nella cache. Questo approccio è un po 'spaventoso nel fatto che se per qualche ragione (errore di rete, ad esempio) uno dei nodi non è sincronizzato, quando una richiesta va a quel nodo, i dati che l'utente vede non saranno accurati rispetto a ciò che è attualmente nel DB. Ancora peggio, se fanno un'altra richiesta e questo colpisce un nodo diverso, vedranno dati diversi e questo sarà fonte di confusione per l'utente. Centralizzando i dati, elimini questo problema. Ora, si potrebbe quindi sostenere che la cache centralizzata ha bisogno del controllo della concorrenza attorno agli aggiornamenti della stessa chiave di dati in cache. Se sono disponibili due aggiornamenti simultanei per la stessa chiave, in che modo si assicura che i due aggiornamenti non si stompano reciprocamente? Il mio pensiero qui è di non preoccuparmi nemmeno di questo; quando si verifica un aggiornamento, rilasciare l'oggetto dalla cache (e scrivere direttamente nel DB) e lasciarlo ricaricare nella prossima lettura. È più sicuro e più facile in questo modo. Se non si desidera farlo, è possibile utilizzare la funzionalità CAS (Check-And-Set) invece per il controllo ottimistico della concorrenza se si desidera veramente aggiornare sia la cache che il db sugli aggiornamenti.

Quindi, per riassumere, è possibile risparmiare denaro e ottimizzare le macchine del livello dell'app se si centralizzano i dati memorizzati nella cache. È inoltre possibile ottenere una maggiore precisione di tali dati in quanto si hanno meno problemi di sincronizzazione dei dati da affrontare. Spero che aiuti.

+0

Grazie per la risposta. Puoi solo spiegare i vantaggi della cache centralizzata, perché di nuovo potrebbe aumentare il sovraccarico sul mio server. Attualmente ha circa 5000 utenti simultanei. Nota: secondo le statistiche attuali ora sto recuperando anche la memoria in un determinato momento. –

+0

Aggiornato dalla risposta per includere alcuni vantaggi ... – cmbaxter

+0

Thanx Cmbaxter ... Questo aiuta davvero ... –

8

Innanzitutto, provare a dimenticare l'ottimizzazione prematura. Hai davvero bisogno del cache? 99% che non ne hai bisogno. In questo caso la soluzione è nella rimozione del codice ridondante.

Se tuttavia ne avete bisogno, provate a smettere di reinventare le ruote. Ci sono librerie perfette pronte all'uso. Ad esempio ehCache con modalità distribuita.

+0

Grazie per la risposta. Ho circa 5000 utenti simultanei, quindi non posso rimuovere la cache suppongo. cercherò su ehCache ... –

2

Utilizzare HazelCast. Permette la sincronizzazione dei dati tra i server tramite protocollo multicast. È facile da usare Supporta il blocco e altre funzionalità.