Utilizzo di Memcached: è buona norma aggiornare la cache durante l'aggiornamento del database?


13

Questa domanda riguarda le migliori pratiche in architettura.

La nostra architettura attuale

Ho una classe PHP che accede a MySQL per informazioni sull'utente. Chiamiamolo User. Usersi accede più volte, quindi abbiamo implementato livelli di cache per ridurre il carico.

Il primo livello è ciò che chiamiamo cache "per richiesta". Dopo che i dati sono stati recuperati da MySQL, archiviamo i dati in una proprietà privata di User. Eventuali richieste successive per i dati restituiscono la proprietà invece di richiedere nuovamente i dati da MySQL.

Poiché la richiesta Web è attiva e muore in base alla richiesta, questa cache impedisce all'applicazione di accedere a MySQL più di una volta in una singola richiesta.

Il nostro secondo livello è Memcached. Quando la proprietà privata è vuota, controlliamo prima Memcached per i dati. Se Memcached è vuoto, interroghiamo MySQL per i dati, aggiorniamo Memcached e aggiorniamo la proprietà privata di User.

La domanda

La nostra applicazione è un gioco e talvolta è indispensabile che alcuni dati siano il più aggiornati possibile. Nell'arco di circa cinque minuti, una richiesta di lettura per i dati dell'utente può avvenire 10 o 11 volte; quindi potrebbe verificarsi un aggiornamento. Le successive richieste di lettura devono essere aggiornate o la meccanica di gioco fallisce.

Quindi, ciò che abbiamo fatto è implementare un pezzo di codice che viene eseguito quando si verifica un aggiornamento del database. Questo codice imposta la chiave in Memcached con i dati aggiornati, quindi tutte le successive richieste a Memcached sono aggiornate.

È ottimale? Ci sono problemi di prestazioni o altri "problemi" di cui dovremmo essere a conoscenza quando cerchiamo di mantenere una sorta di "cache vivente" come questa?


Che cosa ha a che fare con l'eliminazione e l'aggiunta di nuovi dati?
Mike Nakis,

Chiarito il titolo della domanda.
Stephen,

Perché non scadere i dati memorizzati nella cache? L'aggiornamento significa che dovrai assicurarti che l'aggiornamento sia mantenuto (quindi se i nuovi dati devono essere aggiornati in questo modo, dovrai continuare a cambiare l'aggiornamento). La scadenza della cache significa che tutto è stato estratto di nuovo dal database --- e tutti i nuovi aggiornamenti non richiedono nuove modifiche al codice di aggiornamento. Il rovescio della medaglia è che il carico del database potrebbe essere maggiore.
Peter K.

@Peter Sì, ci abbiamo pensato anche noi. Se non emergono altri problemi con il nostro approccio attuale, resteremo fedeli. Altrimenti potremmo andare con quello che hai descritto.
Stephen,

1
@Stephen L'approccio che descrivi si chiama "Scrivi attraverso la cache" ed è un approccio abbastanza comune.
Sripathi Krishnan,

Risposte:


10

La mia raccomandazione è di esaminare il profilo di utilizzo e i requisiti per la cache.

Non vedo alcun motivo per cui lasceresti dati non aggiornati in memcached. Penso che tu abbia scelto l'approccio giusto, ovvero: aggiorna il DB.

In ogni caso, avrai bisogno di un wrapper per l'aggiornamento del tuo DB (che hai fatto). Il tuo codice per aggiornare l'utente nel DB e in-RAM dovrebbe anche fare una spinta a memcached, O una scadenza in memcached.

Ad esempio - Se gli utenti eseguono normalmente un aggiornamento una volta per sessione come parte della disconnessione, non ha molto senso aggiornare i dati nella cache (ad es. Punteggio elevato totale) - è necessario scadere immediatamente.

Tuttavia, se aggiorneranno i dati (ad es. Lo stato attuale del gioco) e dopo 0,2 secondi avrai un hit immediato della pagina PHP che richiederà i dati, li vorresti nuovi nella cache.


3

Non lo farei proprio come hai delineato. Quello che devi fare è decidere se hai effettivamente bisogno di dati completamente aggiornati. Quindi, se ne hai bisogno, decidi quali parti dei dati devono essere sempre aggiornate e separale dalle cose che possono essere memorizzate nella tua architettura.

Ad esempio, probabilmente desideri aggiornare l'indirizzo e-mail dell'utente non appena lo cambiano, quindi non invii messaggi di posta elettronica all'indirizzo errato, ma è improbabile che la data di nascita o cognome dell'utente debba essere completamente aggiornato per offrire un'esperienza utente decente. (NB Non sto usando un esempio di architettura di gioco in quanto non so a quale tipo di gioco puntarlo, e penso che questo sia abbastanza facile da capire).

In questo modo sono disponibili due set di dati chiari: dati memorizzabili nella cache a breve e lungo termine. Probabilmente puoi cavartela con una durata della cache di circa un minuto sui dati a breve termine, solo per scaricare il carico sul DB, ma i dati a lungo termine possono essere lasciati nella cache su una durata scorrevole fino a quando è Usato.

Quindi è necessario gestire gli aggiornamenti. Innanzitutto esaminerei l'utilizzo di un trigger DB per rimuovere semplicemente gli elementi dalla cache una volta scaduti. Ciò costringerà il tuo livello aziendale ad attivare un aggiornamento della cache alla successiva richiesta dei dati, liberando spazio nella cache se i dati non vengono utilizzati (ad esempio se un utente modifica il proprio indirizzo e-mail, quindi si disconnette immediatamente) . Se questo causerà problemi di prestazioni nell'interfaccia utente (ovvero introduci un ritardo eccessivo durante l'attesa degli aggiornamenti della cache), puoi guardare semplicemente attivando la chiamata della cache dopo che l'elemento è stato rimosso dalla cache. Vorrei anche ottimizzare i tempi di lettura del DB per questo piccolo set di dati, per garantire che ogni ritardo indotto nell'aggiornamento della cache sia minimo (questo dovrebbe essere più semplice in quanto è necessario solo caricare i dati di cui si ha realmente bisogno).

Quello che non farei, in ogni caso, è aggiungere un metodo aggiuntivo per riempire la cache, poiché in questo caso dovrai mantenere la chiamata (e gli hook API ecc.) In due punti.

Per quanto riguarda i gotcha, la cosa principale di cui devi fare attenzione se stai scrivendo direttamente nella cache è la sincronizzazione. Se molti thread tentano di leggere mentre stai eseguendo l'aggiornamento silenzioso, potresti avere alcuni seri problemi di dati non validi, che annulleranno il punto di cercare di mantenere i dati aggiornati in primo luogo.

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.