NDB gestisce le cache per te. Esistono due livelli di memorizzazione nella cache: una cache in-context 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 per soddisfare 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 sia configurata 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
Opzioni di contesto argomenti.
Ad esempio, puoi chiamare
key.get(use_cache=False, use_memcache=False)
per ignorare la memorizzazione nella cache. Puoi anche modificare la policy di memorizzazione nella cache predefinita
in un contesto NDB come descritto di seguito.
Attenzione: quando utilizzi il visualizzatore Datastore della Console di amministrazione per modificare i contenuti di Datastore, i valori memorizzati nella cache non vengono aggiornati. Di conseguenza, la cache potrebbe essere incoerente. Per la cache in-context, in genere non si tratta di 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 corrente,
utilizza la funzione ndb.get_context().
Attenzione: non ha senso condividere gli oggetti
Context tra più thread o richieste.
Non salvare il contesto come variabile globale.
È possibile salvarlo in una variabile locale o thread-local.
Gli oggetti di contesto hanno metodi per impostare le policy di memorizzazione nella cache e manipolare la cache.
La cache in-context
La cache in-context persiste solo per la durata di un singolo thread. Ciò significa che a ogni richiesta HTTP in entrata viene assegnata una nuova cache in-context ed è "visibile" solo al codice che gestisce la richiesta. Se l'applicazione genera thread aggiuntivi durante la gestione di una richiesta, questi thread avranno anche una nuova cache in-context separata.
La cache in-context è veloce e risiede in memoria. Quando una funzione NDB scrive in Datastore, scrive anche nella cache in-context. Quando una funzione NDB legge un'entità, controlla prima la cache in-context. Se l'entità viene trovata, non viene eseguita 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 in-context, viene utilizzato al posto del valore recuperato dalla query Datastore. I risultati delle query vengono scritti di nuovo nella cache in-context se la policy di memorizzazione nella cache lo prevede (ma mai in Memcache).
Quando si eseguono query a lunga esecuzione nelle attività in background, è possibile che la cache in-context consumi grandi quantità di memoria. Questo perché la cache conserva una copia di ogni entità recuperata o archiviata nel contesto corrente. Per evitare eccezioni di memoria nelle attività a lunga esecuzione, puoi disattivare la cache o impostare una policy 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-context (millisecondi rispetto a 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 sia a Memcache potrebbe essere applicato solo a uno dei due. Per mantenere la coerenza in questi casi (possibilmente a scapito delle prestazioni) l'entità aggiornata viene eliminata da Memcache e poi scritta in Datastore. Un'operazione di lettura successiva rileverà che l'entità non è presente in Memcache, la recupererà da Datastore e la aggiornerà in 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 di policy
La memorizzazione automatica nella cache è comoda per la maggior parte delle applicazioni, ma la tua applicazione potrebbe essere insolita e potresti voler disattivare la memorizzazione automatica nella cache per alcune o tutte le entità. Puoi controllare il comportamento delle cache impostando le funzioni di policy. Esiste una funzione di policy per la cache in-process, impostata con
e un'altra per Memcache, impostata con
Ogni funzione di policy accetta una chiave e restituisce un risultato booleano.
Se restituisce False, l'entità identificata dalla
chiave non verrà salvata nella cache corrispondente.
Ad esempio, per ignorare la cache in-process per tutte le
Account entità, 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.
Le policy predefinite memorizzano nella cache tutte le entità.
Esiste anche una funzione di policy di Datastore che determina quali entità vengono scritte in Datastore:
Funziona come le funzioni di policy della cache in-context e di Memcache:
se la funzione di policy di Datastore restituisce False
per una determinata chiave, l'entità corrispondente non verrà scritta nel
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 policy di memorizzazione nella cache, puoi passare True o
False anziché una funzione che restituisce sempre lo stesso valore.
Memcache fa scadere automaticamente gli elementi quando la memoria è insufficiente. Puoi impostare una funzione di policy di timeout di 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 indefinito
(a condizione che il server Memcache abbia 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 contesto nuovo di zecca inizia con una cache in-process vuota.
Sebbene le funzioni di policy siano molto flessibili, in pratica la maggior parte delle policy sono semplici. Ad esempio,
- Non memorizzare nella cache le entità appartenenti a una classe di modelli specifica.
- Imposta il timeout di Memcache per le entità in questa classe di modelli su 30 secondi.
- Le entità in questa classe di modelli non devono essere scritte in Datastore.
Per evitare di dover scrivere e aggiornare continuamente funzioni di policy banali (o, peggio ancora, di sostituire le policy per ogni operazione utilizzando le opzioni di contesto), le funzioni di policy predefinite ottengono la classe di modelli dalla chiave passata e poi cercano nella classe di modelli variabili di classe specifiche:
| Variabile di 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 la policy di Memcache predefinita. |
_use_datastore | bool | Specifica se archiviare le entità in Datastore; sostituisce la policy di Datastore predefinita. |
_memcache_timeout | int | Durata massima delle entità in Memcache; sostituisce la policy di timeout di Memcache predefinita. |
Nota: questa è una funzionalità della funzione di policy predefinita per ogni policy.
Se specifichi una tua funzione di policy, ma vuoi anche utilizzare la policy predefinita, chiama esplicitamente le funzioni di policy predefinite come metodi statici della classe Context:
default_cache_policy(key)default_memcache_policy(key)default_datastore_policy(key)default_memcache_timeout_policy(key)