Memorizzazione nella cache NDB

NDB gestisce le cache per te. Esistono due livelli di memorizzazione nella cache: una cache contestuale e un gateway al servizio di memorizzazione nella cache standard di App Engine, memcache. Entrambe le cache sono abilitate per impostazione predefinita per tutti i tipi di entità, ma possono essere configurati per soddisfare esigenze avanzate. Inoltre, NDB implementa una funzione chiamata batch automatico, che cerca di raggruppare le operazioni per ridurre al minimo i round trip del server.

Introduzione

La memorizzazione nella cache è utile per la maggior parte dei tipi di applicazioni. NDB memorizza automaticamente nella cache Dati che scrive o legge (a meno che un'applicazione non li configuri). La lettura dalla cache è più veloce rispetto alla lettura da Datastore.

È possibile modificare il comportamento di memorizzazione nella cache di molte funzioni NDB passando Argomenti Opzioni di contesto. Ad esempio, potresti chiamare key.get(use_cache=False, use_memcache=False) per aggirare la memorizzazione nella cache. Puoi anche modificare di memorizzazione nella cache in un contesto NDB come descritto di seguito.

Attenzione: Quando utilizzi il visualizzatore Datastore della console di amministrazione per modificare i contenuti del datastore, i valori memorizzati nella cache non verranno aggiornati. Di conseguenza, la cache potrebbe non essere coerente. Generalmente non è un problema per la cache contestuale. Per Memcache, ti consigliamo di utilizzare la console di amministrazione per svuotare la cache.

Oggetti di contesto

La gestione della cache utilizza una classe denominata Context: ogni thread e ogni transazione viene eseguita in un contesto. Poiché ogni richiesta HTTP in entrata avvia un nuovo thread, ogni richiesta viene eseguita con nuovo contesto. Per accedere al contesto attuale, usa la funzione ndb.get_context().

Attenzione: non ha senso condividere Context oggetti tra più thread o richieste. Non salvare il contesto come variabile globale. È possibile memorizzarla in una variabile locale o in thread locale.

Gli oggetti di contesto prevedono metodi per impostare i criteri di cache e manipolando in altro modo la cache.

La cache in-contesto

La cache contestuale viene mantenuta solo per la durata di un singolo thread. Ciò significa che ogni viene assegnata una nuova cache contestuale ed è "visibile" alla richiesta HTTP in arrivo solo al codice gestisce la richiesta. Se l'applicazione genera altri thread durante la gestione di una richiesta, questi thread avranno anche una nuova cache contestuale separata.

La cache nel contesto è veloce: questa cache risiede in memoria. Quando una funzione NDB scrive Datastore, inoltre scrive nella cache contestuale. Quando una funzione NDB legge un'entità, controlla prima la cache contestuale. Se l'entità viene trovata in questa posizione, non è richiesta nessuna interazione con Datastore posto.

Quando una funzione NDB esegue una query su Datastore, l'elenco dei risultati viene recuperato da per il datastore. Tuttavia, se un singolo risultato si trova nella cache contestuale, viene utilizzato al posto del valore recuperato dalla query Datastore. I risultati della query vengono riscritti nella cache contestuale se lo è (ma mai a Memcache).

Quando si eseguono query a lunga esecuzione in attività in background, è possibile che la cache contestuale per consumare grandi quantità di memoria. Questo perché la cache conserva una copia di ogni entità viene recuperato o archiviato nel contesto corrente. Per evitare eccezioni di memoria nelle attività a lunga esecuzione, puoi disabilitare la cache o impostare un criterio che escluda che consumano più memoria.

Memcache

Memcache è il servizio di memorizzazione nella cache standard di App Engine, più veloce di Datastore, ma più lenta della cache contestuale (millisecondi contro microsecondi).

Per impostazione predefinita, un contesto non transazionale memorizza nella cache tutte le entità in memcache. Tutti i contesti di un'applicazione usare lo stesso server memcache e vedere un insieme coerente di valori memorizzati nella cache.

Memcache non supporta le transazioni. Pertanto, un aggiornamento da applicare sia Datastore e memcache possono essere create solo per uno dei due. Per mantenere la coerenza in questi casi (probabilmente a scapito delle prestazioni), l'entità aggiornata viene eliminata da memcache e quindi scritte in Datastore. Un'operazione di lettura successiva troverà l'entità mancante in memcache, la recupera dal Datastore e poi lo aggiorni in memcache come effetto collaterale della lettura. Inoltre, NDB legge all'interno delle transazioni ignorando la memcache.

Quando le entità sono scritte all'interno di una transazione, memcache non viene usati; al momento del commit della transazione, il relativo contesto tenterà per eliminare tutte queste entità da memcache. Tieni presente, tuttavia, che errori che potrebbero impedire tali eliminazioni.

Funzioni relative ai criteri

La memorizzazione nella cache automatica è comoda per la maggior parte delle applicazioni, ma forse l'applicazione è insolita e vuoi disattivare la memorizzazione nella cache automatica per alcune o tutte le entità. Puoi controllare il comportamento delle cache impostando funzioni di criterio. È presente una funzione di criterio per la cache in-process, impostata con

context = ndb.get_context()
context.set_cache_policy(func)

e un'altra per memcache, impostata con

context = ndb.get_context()
context.set_memcache_policy(func)

Ogni funzione dei criteri accetta una chiave e restituisce un risultato booleano. Se restituisce False, l'entità identificata non verrà salvata nella cache corrispondente. Ad esempio, per ignorare la cache in-process per Account entità, potresti scrivere

context = ndb.get_context()
context.set_cache_policy(lambda key: key.kind() != 'Account')

(Tuttavia, continua a leggere per trovare un modo più semplice per realizzare la stessa cosa.) Per praticità, puoi passare True o False invece di una funzione che restituisce sempre lo stesso valore. I criteri predefiniti memorizzano nella cache tutte le entità.

Esiste anche una funzione dei criteri Datastore che stabilisce quali entità vengono scritte nel datastore:

context = ndb.get_context()
context.set_datastore_policy(func)

Funziona in modo simile alle funzioni della cache contestuale e dei criteri memcache: se la funzione dei criteri Datastore restituisce False per una determinata chiave, l'entità corrispondente non verrà scritta Datastore. (Può essere scritto nella cache in-process o in memcache se le funzioni dei criteri lo consentono.) Questo può essere utile nei casi in cui disponi di dati di tipo entità che si desidera memorizzare nella cache, ma che non è necessario archiviare in Datastore. Come per i criteri della cache, puoi passare True o False invece di una funzione che restituisce sempre lo stesso valore.

Memcache fa scadere automaticamente gli elementi quando la memoria è ridotta. Puoi impostare una funzione del criterio di timeout memcache per determinare durata massima dell'entità nella cache:

context = ndb.get_context()
context.set_memcache_timeout_policy(func)

Questa funzione viene chiamata con un argomento chiave e deve restituire un numero intero che specifica la durata massima in secondi; 0 o None significa indefinito (purché il server memcache abbia memoria sufficiente). Per praticità, puoi semplicemente passare una costante intera invece di una funzione che restituisce sempre lo stesso valore. Per ulteriori informazioni sui timeout, consulta la documentazione relativa alle memcache.

Nota: Non esiste un criterio di durata distinto per la cache contestuale: la durata della cache è uguale a quella del suo contesto, una singola richiesta HTTP in entrata. Tuttavia, puoi svuotare la cache in-process chiamando
context = ndb.get_context()
context.clear_cache()

Un contesto completamente nuovo inizia con una cache in-process vuota.

Anche se le funzioni dei criteri sono molto flessibili, Nella pratica, la maggior parte dei criteri è semplice. Ad esempio,

  • Non memorizzare nella cache entità che appartengono a una classe di modello specifica.
  • Imposta il timeout memcache per le entità in questa classe del modello su 30 secondi.
  • Le entità in questa classe di modello non devono essere scritte in Datastore.

Per evitare di dover scrivere e aggiornare continuamente funzioni dei criteri (o, peggio ancora, eseguire l'override dei criteri per utilizzando le opzioni di contesto), le funzioni predefinite del criterio ottenere la classe del modello dalla chiave passata e cerca variabili di classe specifiche nella classe del modello:

Variabile classe Tipo Descrizione
_use_cache bool Specifica se archiviare le entità nella cache in-process. sostituisce il criterio predefinito della cache in-process.
_use_memcache bool Specifica se archiviare le entità in memcache; sostituisce il criterio memcache predefinito.
_use_datastore bool Specifica se archiviare le entità nel datastore. sostituisce il criterio Datastore predefinito.
_memcache_timeout int Durata massima delle entità in memcache; esegue l'override del criterio di timeout memcache predefinito.

Nota: Si tratta di una funzionalità della funzione dei criteri predefiniti per ogni criterio. Se specifichi la tua funzione per le norme, ma vuoi anche ricorrere alla per il criterio predefinito, richiama esplicitamente le funzioni del criterio predefinito come metodi statici della classe Context:

  • default_cache_policy(key)
  • default_memcache_policy(key)
  • default_datastore_policy(key)
  • default_memcache_timeout_policy(key)