Le cache a livello di applicazione appartengono ai server Web?

2

Un collega e io non siamo d'accordo su dove dovrebbe andare la cache per un server web. Attualmente lo abbiamo implementato come cache globale (statica) in-process, cosa che non condivido. Penso che la cache dovrebbe essere scaricata su un altro server usando qualcosa di simile a redis. Ho sempre avuto l'impressione che lo stato globale sia cattivo e particolarmente cattivo nei server web. Lo stato appartiene ai database. Tuttavia, il mio collega mostra un punto equo che è che lo scaricamento introduce il sovraccarico del trasferimento di rete per ogni hit della cache. Non posso discuterne, ma la cache in-process sembra essere pessima. So che alla fine incontreremo problemi di concorrenza con la cache globale.

Le cache a livello di applicazione appartengono ai server Web e in quali circostanze è una buona scelta?

Modifica: alcune informazioni su ciò che viene memorizzato nella cache: in questo caso abbiamo un microservizio che trasforma alcuni dati da un altro servizio prima che sia servito ai client. Il motivo per la memorizzazione nella cache è duplice: 1) per ridurre il carico sul servizio di origine e 2) per memorizzare nella cache i risultati della trasformazione dei dati.

    
posta ConditionRacer 17.04.2016 - 20:00
fonte

3 risposte

9

Come sempre, è necessario distinguere: quali informazioni devono essere memorizzate nella cache?

Vado sempre con queste semplici regole:

  • Le informazioni che ogni istanza del server web può calcolare da sé dovrebbero essere inserite in una cache RAM, poiché devono essere accessibili al più presto su richiesta ma non devono essere condivise (non modificare o non contenere informazioni rilevanti per altri server).
    • risultati di calcoli complessi che ogni server può eseguire indipendentemente
    • stato immutabile e condiviso (ad es. risultati DB che non cambiano: i primi 10 utenti della settimana precedente, ...)
    • Cache di metadati di codice (ad esempio annotazioni o calcoli risultanti)
  • Lo stato condiviso che deve essere accessibile più rapidamente di quanto può fare il tuo DB dovrebbe entrare in un server cache separato [cluster] (ad esempio Redis, Memcached, ...). Si noti che molte di queste cose possono essere affrontate da un bilanciamento del carico intelligente.
    • Informazioni sui ban degli utenti e degli utenti
    • Stato sessione (i bilanciatori di carico possono gestirlo utilizzando cookie di affinità se l'architettura dell'applicazione lo consente)
    • code, eventi del dominio
  • Lo stato condiviso che non deve essere accessibile più rapidamente di quanto può fare il DB deve rimanere nel DB. Usare cache per cose che non devono necessariamente essere memorizzate nella cache è una fonte inutile di errori e fallimenti.

Per quanto riguarda la modifica della domanda: IMHO questi dati rientrano nella prima categoria: ogni server può calcolare la trasformazione per se stesso. Tuttavia, se qui stiamo parlando di gigabyte di dati, suggerirei di eseguire la trasformazione una sola volta, di archiviare il risultato nel DB e di memorizzare solo le parti richieste più frequentemente. Potresti anche inserire altri 16 GB di RAM nei tuoi server ... Probabilmente meno costosi dell'implementazione di diversi livelli di cache.

    
risposta data 17.04.2016 - 20:25
fonte
2

Se quello che cerchi è l'eliminazione dello stato globale nella tua applicazione, la parola chiave static sicuramente fa schifo nel tuo codice (dici che non ti piace, quindi presumo che tu sappia che svantaggi la parola chiave static porta allo sviluppo di applicazioni).

Considerando il problema della cache, che sia in-process o out-processato a un sistema come Redis , non importa davvero cosa esattamente che stavi usando, che si tratti di memoria, file o Redis, purché il livello della cache fosse static , tutto sarebbe rimasto lo stesso (sarebbe globale).

Il bisogno di un buon livello di memorizzazione nella cache non è sicuramente un problema banale. Durante il mio divenire, spero, un programmatore migliore abbia passato circa 5 versioni di interfacce di cache layer (che io o una squadra ero in codice), prima di arrivare finalmente a una soluzione che mi piacesse.

Ma anche in questo caso, avere un livello di caching ben documentato (un static uno a parte, perché è una cosa che cerco di evitare nelle mie applicazioni) non è una soluzione a un problema ma semplicemente un mezzo per raggiungerlo.

Il problema è qualcosa di completamente diverso, ovvero la mia applicazione è lenta, voglio memorizzare nella cache determinati dati e voglio farlo in modo efficiente in base al design della mia applicazione .

I due problemi che si verificano più spesso quando si prende in considerazione la creazione di un livello di memorizzazione nella cache sono i seguenti:

  • Voglio condividere la cache tra i processi?
  • Mi preoccupo di avere migliaia di processi, ognuno con la propria cache che sta fissando il pool di memoria?

Esistono molti tipi diversi di applicazioni: le app standalone installate dal cliente, le applicazioni Web, i servizi Web (REST, SOAP), le presentazioni Web, ...

Per tutti questi uno strato di cache può essere considerato come una possibilità per rendere l'applicazione più veloce, ma c'è un problema, le applicazioni sono completamente diverse e per approcci così diversi devono essere presi quando si tenta di progettare la cache.

Cache per i servizi Web

I servizi Web, REST, SOAP, di solito hanno un compito. Connessione diretta astratta a un database in modo che i clienti possano consumare i dati del database senza che tu sia costretto a esporre la tua origine dati. Oltre a questo possono essere aggiunti strati intermedi (come il bilanciamento o la cache in questione) per migliorare le prestazioni (in genere calcolate dal tempo di risposta).

Se vuoi una cache in elaborazione o una in outsourcing (file / Redis, non importa), dipende dal design della tua applicazione.

Considera un servizio web PHP. PHP funziona in modo tale che per ogni richiesta venga creata una nuova istanza di un'applicazione. Ciò significa che se memorizzi i dati in-process nella cache, i dati memorizzati nella cache sarebbero disponibili solo all'interno della singola richiesta, il che potrebbe velocizzare l'applicazione, ma se un altro endpoint utilizza gli stessi dati dell'endpoint che ha colpito per primo, il secondo l'endpoint dovrebbe caricare nuovamente i dati, poiché non può accedere ai dati memorizzati nella cache dal processo endpoint.

Naturalmente, vorrai condividere lo stato della cache, quindi avresti solo un'opzione. O crea il tuo sistema di caching, molto probabilmente usando i file, o usa un sistema come Redis, così diversi processi possono accedere agli stessi dati e non hanno bisogno di colpire il database.

D'altra parte, se si avesse un servizio Web, che avrebbe avuto solo un'istanza e una memoria condivisa tra gli endpoint, forse la cache in-process sarebbe in realtà un'alternativa migliore, considerando che più endpoint sarebbero ancora in grado di accedervi .

Il tuo collega ha paura del rendimento, perché devi accedere al server Redis piuttosto che accedere direttamente alla memoria. Credimi, questo è davvero il minimo dei problemi. La riduzione delle prestazioni è talmente piccola che è ancora meglio condividere lo stato del database in questo modo piuttosto che dover eseguire query direttamente nel database.

È possibile definire come si desidera memorizzare i dati in Redis, scegliere il tipo di dati migliore per il problema. È abbastanza ovvio che attraversare un albero di ricerca binario per una combinazione di valori basata su un hash sarà più veloce di dover interrogare il database e comporre i dati all'interno.

Sì, i database hanno cache in sé, ma anche in questo caso:

  1. query db - > db chiama la sua cache - > db ottiene i dati dalla cache - > db restituisce i dati
  2. query cache - > ottieni dati

Meno passaggi di solito significa che l'operazione sarà più veloce e in questo caso lo è.

Dovresti mettere in cache nella cache in outsourcing cose che sai saranno condivise tra le richieste (i dati dal database sono generalmente condivisi). Per quanto tempo e quanti dati vuoi memorizzare nella cache dipende da te e dalle tue regole aziendali.

Dovresti memorizzare nella cache le cose in-process, che sai essere disponibili durante una specifica richiesta, sarà necessario essere disponibili più volte durante la richiesta ma non influenzare altre richieste.

    
risposta data 17.04.2016 - 20:39
fonte
1

Nel tuo caso in cui usi i microservizi dovresti usare la cache condivisa.

Il ragionamento è che uno dei principali vantaggi dei microservizi è la possibilità di ridimensionarli su più istanze.

Se si esegue questa operazione e una richiesta incomming colpisce l'istanza del servizio 2 anziché 1 l'istanza 2 potrebbe trarre vantaggio dal risultato memorizzato nella cache di una precedente chiamata all'istanza 1

A meno che non si stiano utilizzando gli stessi dati più volte all'interno di una singola transazione richiesta-risposta, nella memorizzazione nella cache del processo è disponibile un'utilità limitata.

    
risposta data 17.04.2016 - 22:34
fonte

Leggi altre domande sui tag