NDB gestisce le cache per te. Esistono due livelli di memorizzazione nella cache: una cache in contesto 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 configurate in base alle esigenze avanzate. Inoltre, NDB implementa una funzionalità chiamata batch automatico, che tenta 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 i dati che scrive o legge (a meno che un'applicazione non lo configuri in modo diverso). La lettura dalla cache è più veloce della lettura da Datastore.
Puoi 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 ignorare la memorizzazione nella cache. Puoi anche modificare la norma di memorizzazione nella cache
predefinita in un contesto NDB come descritto di seguito.
Attenzione:quando utilizzi Datastore Viewer della Console di amministrazione per modificare i contenuti di Datastore, i valori memorizzati nella cache non vengono aggiornati. Pertanto, la cache potrebbe non essere coerente. Per la cache in contesto, in genere non è un problema. 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 nuovo
contesto. Poiché ogni richiesta HTTP in entrata avvia un nuovo thread, ogni richiesta viene eseguita anche con un nuovo contesto. Per accedere al contesto attuale,
utilizza la funzione ndb.get_context()
.
Attenzione:non ha senso condividere
oggetti Context
tra più thread o richieste.
Non salvare il contesto come variabile globale.
L'archiviazione in una variabile locale o locale al thread è accettabile.
Gli oggetti di contesto hanno metodi per impostare le norme della cache e manipolare la cache.
La cache contestuale
La cache contestuale viene mantenuta solo per la durata di un singolo thread. Ciò significa che a ogni richiesta HTTP in entrata viene assegnata una nuova cache in contesto ed è "visibile" solo al codice che gestisce la richiesta. Se la tua applicazione genera thread aggiuntivi durante la gestione di una richiesta, anche questi thread avranno una nuova cache in-context separata.
La cache in contesto è veloce e risiede in memoria. Quando una funzione NDB scrive in Datastore, scrive anche nella cache in contesto. Quando una funzione NDB legge un'entità, controlla prima la cache in contesto. Se l'entità viene trovata, non si verifica alcuna interazione con Datastore.
Quando una funzione NDB esegue una query su Datastore, l'elenco dei risultati viene recuperato da 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 i criteri della cache lo prevedono (ma mai in Memcache).
Con l'esecuzione di query a lunga esecuzione nelle attività in background, è possibile che la cache contestuale consumi grandi quantità di memoria. Questo perché la cache conserva una copia di ogni entità recuperata o archiviata nel contesto attuale. Per evitare eccezioni di memoria nelle attività di lunga durata, puoi disattivare la cache o impostare un criterio che escluda le entità che consumano più memoria.
Memcache
Memcache è il servizio di memorizzazione nella cache standard di App Engine, molto più veloce di Datastore ma più lento della cache in contesto (millisecondi anziché microsecondi).
Per impostazione predefinita, un contesto non transazionale memorizza nella cache tutte le entità in memcache. Tutti i contesti di un'applicazione utilizzano lo stesso server memcache e vedono un insieme coerente di valori memorizzati nella cache.
Memcache non supporta le transazioni. Pertanto, un aggiornamento destinato a essere applicato sia a Datastore che a memcache potrebbe essere apportato solo a uno dei due. Per mantenere la coerenza in questi casi (possibilmente a scapito delle prestazioni), l'entità aggiornata viene eliminata dalla memcache e poi scritta nel datastore. Un'operazione di lettura successiva troverà l'entità mancante nella memcache, la recupererà da Datastore e poi la aggiornerà nella memcache come effetto collaterale della lettura. Inoltre, le letture NDB all'interno delle transazioni ignorano Memcache.
Quando le entità vengono scritte all'interno di una transazione, memcache non viene utilizzato; quando la transazione viene eseguita, il relativo contesto tenta di eliminare tutte queste entità da memcache. Tieni presente, tuttavia, che alcuni errori potrebbero impedire queste eliminazioni.
Funzioni dei criteri
La memorizzazione automatica nella cache è comoda per la maggior parte delle applicazioni, ma forse la tua applicazione è insolita e vuoi disattivare la memorizzazione automatica nella cache per alcune o tutte le entità. Puoi controllare il comportamento delle cache impostando le funzioni dei criteri. Esiste una funzione di criteri per la cache in-process, impostata con
e un altro per memcache, impostato con
Ogni funzione dei criteri accetta una chiave e restituisce un risultato booleano.
Se restituisce False
, l'entità identificata da questa
chiave non verrà salvata nella cache corrispondente.
Ad esempio, per ignorare la cache in-process per tutte le entità Account
, puoi scrivere
Tuttavia, continua a leggere per scoprire un modo più semplice per ottenere lo stesso risultato.
Per comodità, puoi passare True
o False
anziché una funzione che restituisce sempre lo stesso valore.
I criteri predefiniti memorizzano nella cache tutte le entità.
Esiste anche una funzione di policy Datastore che regola le entità scritte in Datastore stesso:
Funziona come le funzioni dei criteri di cache e memcache in contesto:
se la funzione dei criteri Datastore restituisce False
per una determinata chiave, l'entità corrispondente non verrà scritta in
Datastore.
(Potrebbe essere scritto nella cache in-process o in memcache
se le relative funzioni di policy lo consentono.)
Questo può essere utile nei casi in cui hai dati simili a entità
che vuoi memorizzare nella cache, ma che non devi archiviare
in Datastore.
Come per le norme di gestione della cache, puoi passare True
o
False
anziché una funzione che restituisce sempre lo stesso valore.
Memcache automatically expires items when under memory pressure. Puoi impostare una funzione di criteri di timeout memcache per determinare la durata massima di un'entità nella cache:
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 durata indefinita (finché il server memcache ha memoria sufficiente).
Per comodità, puoi semplicemente passare una costante intera
anziché una funzione che restituisce sempre lo stesso valore.
Per ulteriori informazioni sui timeout, consulta la documentazione di Memcache.
Un nuovo contesto inizia con una cache in corso vuota.
Sebbene le funzioni dei criteri siano molto flessibili, in pratica la maggior parte dei criteri è semplice. Ad esempio,
- Non memorizzare nella cache le entità appartenenti a una classe di modello specifica.
- Imposta il timeout della memcache per le entità in questa classe di modello su 30 secondi.
- Le entità di questa classe di modelli non devono essere scritte in Datastore.
Per risparmiarti il lavoro di scrivere e aggiornare continuamente funzioni di criteri banali (o, peggio ancora, di ignorare i criteri per ogni operazione utilizzando le opzioni di contesto), le funzioni di criteri predefinite ottengono la classe del modello dalla chiave che viene loro passata e poi cercano nella classe del modello variabili di classe specifiche:
Variabile classe | Tipo | Descrizione |
---|---|---|
_use_cache | bool | Specifica se archiviare le entità nella cache in-process; sostituisce la policy di cache in-process predefinita. |
_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; esegue l'override dei criteri Datastore predefiniti. |
_memcache_timeout | int | Durata massima delle entità in memcache; sostituisce il criterio di timeout predefinito di memcache. |
Nota:
Questa è una funzionalità della funzione di policy predefinita per ogni policy.
Se specifichi la tua funzione di policy, ma vuoi anche eseguire il fallback alla policy predefinita, chiama le funzioni di policy predefinite in modo esplicito come metodi statici della classe Context
:
default_cache_policy(key)
default_memcache_policy(key)
default_datastore_policy(key)
default_memcache_timeout_policy(key)