O NDB gere as caches por si. Existem dois níveis de colocação em cache: uma cache no contexto e um gateway para o serviço de colocação em cache padrão do App Engine, o memcache. Ambas as caches estão ativadas por predefinição para todos os tipos de entidades, mas podem ser configuradas para se adequarem a necessidades avançadas. Além disso, o NDB implementa uma funcionalidade denominada processamento automático em lote, que tenta agrupar operações para minimizar as viagens de ida e volta ao servidor.
Introdução
A colocação em cache ajuda a maioria dos tipos de aplicações. O NDB armazena automaticamente em cache os dados que escreve ou lê (a menos que uma aplicação o configure para não o fazer). A leitura a partir da cache é mais rápida do que a leitura a partir do Datastore.
Pode alterar o comportamento de colocação em cache de muitas funções NDB transmitindo argumentos de opções de contexto.
Por exemplo, pode chamar
key.get(use_cache=False, use_memcache=False)
para ignorar o armazenamento em cache. Também pode alterar a política de colocação em cache predefinida num contexto NDB, conforme descrito abaixo.
Aviso: Quando usa o visualizador do Datastore da consola de administração para modificar o conteúdo do Datastore, os valores em cache não são atualizados. Assim, a cache pode ser inconsistente. Geralmente, isto não é um problema para a cache no contexto. Para o Memcache, recomendamos que use a consola de administração para limpar a cache.
Objetos de contexto
A gestão da cache usa uma classe denominada
Context
:
cada thread e cada transação são executadas num novo
contexto. Uma vez que cada pedido HTTP recebido inicia uma nova thread, cada pedido também é executado com um novo contexto. Para aceder ao contexto atual,
use a função ndb.get_context()
.
Atenção: não faz sentido partilhar objetos Context
entre vários pedidos ou threads.
Não guarde o contexto como uma variável global!
Armazená-lo numa variável local ou específica do segmento não tem problema.
Os objetos de contexto têm métodos para definir políticas de cache e manipular a cache de outra forma.
A cache no contexto
A cache no contexto persiste apenas durante uma única discussão. Isto significa que cada pedido HTTP de entrada recebe uma nova cache no contexto e só é "visível" para o código que processa esse pedido. Se a sua aplicação gerar discussões adicionais durante o processamento de um pedido, essas discussões também terão uma nova cache no contexto separada.
A cache no contexto é rápida. Esta cache reside na memória. Quando uma função NDB escreve no Datastore, também escreve na cache no contexto. Quando uma função NDB lê uma entidade, verifica primeiro a cache no contexto. Se a entidade for encontrada aí, não ocorre nenhuma interação com o Datastore.
Quando uma função NDB consulta o Datastore, a lista de resultados é obtida a partir do Datastore. No entanto, se algum resultado individual estiver na cache no contexto, é usado em vez do valor obtido a partir da consulta do Datastore. Os resultados da consulta são gravados novamente na cache no contexto se a política de cache o indicar (mas nunca no Memcache).
Com a execução de consultas de longa duração em tarefas em segundo plano, é possível que a cache no contexto consuma grandes quantidades de memória. Isto deve-se ao facto de a cache manter uma cópia de cada entidade que é obtida ou armazenada no contexto atual. Para evitar exceções de memória em tarefas de longa duração, pode desativar a cache ou definir uma política que exclua as entidades que estão a consumir mais memória.
cache de memória
Memcache é o serviço de colocação em cache padrão do App Engine, muito mais rápido do que o Datastore, mas mais lento do que a cache no contexto (milissegundos vs. microssegundos).
Por predefinição, um contexto não transacional coloca em cache todas as entidades na memcache. Todos os contextos de uma aplicação usam o mesmo servidor de memcache e veem um conjunto consistente de valores em cache.
O Memcache não suporta transações. Assim, uma atualização destinada a ser aplicada ao Datastore e ao memcache pode ser feita apenas a um dos dois. Para manter a consistência nestes casos (possivelmente à custa do desempenho), a entidade atualizada é eliminada da memcache e, em seguida, escrita no Datastore. Uma operação de leitura subsequente vai detetar que a entidade está em falta na cache de memória, obtê-la a partir do Datastore e, em seguida, atualizá-la na cache de memória como um efeito secundário da leitura. Além disso, as leituras NDB em transações internas ignoram a Memcache.
Quando as entidades são escritas numa transação, a cache de memória não é usada. Quando a transação é confirmada, o respetivo contexto tenta eliminar todas essas entidades da cache de memória. No entanto, tenha em atenção que algumas falhas podem impedir que estas eliminações ocorram.
Funções de políticas
O armazenamento em cache automático é conveniente para a maioria das aplicações, mas talvez a sua aplicação seja invulgar e queira desativar o armazenamento em cache automático para algumas ou todas as entidades. Pode controlar o comportamento das caches definindo funções de políticas. Existe uma função de política para a cache no processo, definida com
e outro para memcache, definido com
Cada função de política aceita uma chave e devolve um resultado booleano.
Se devolver False
, a entidade identificada por essa chave não é guardada na cache correspondente.
Por exemplo, para ignorar a cache em processamento para todas as entidades Account
, pode escrever
(No entanto, continue a ler para saber como fazer o mesmo de forma mais fácil.)
Para sua conveniência, pode transmitir True
ou False
em vez de uma função que devolve sempre o mesmo valor.
As políticas predefinidas colocam todas as entidades em cache.
Existe também uma função de política do Datastore que rege as entidades que são escritas no próprio Datastore:
Isto funciona como as funções de política de cache no contexto e memcache:
se a função de política do Datastore devolver False
para uma determinada chave, a entidade correspondente não é escrita no
Datastore.
(Pode ser escrito na cache no processo ou na memcache
se as respetivas funções de política o permitirem.)
Isto pode ser útil nos casos em que tem dados semelhantes a entidades que quer colocar em cache, mas que não precisa de armazenar no Datastore.
Tal como para as políticas de cache, pode transmitir True
ou
False
em vez de uma função que devolva sempre o mesmo valor.
O Memcache faz expirar automaticamente os itens quando está sob pressão de memória. Pode definir uma função de política de limite de tempo da memcache para determinar a duração máxima de uma entidade na cache:
Esta função é chamada com um argumento de chave e deve devolver um
número inteiro que especifica o tempo de vida máximo em segundos;
0 ou None
significa indefinido
(enquanto o servidor de memcache tiver memória suficiente).
Para maior comodidade, pode simplesmente transmitir uma constante inteira
em vez de uma função que devolve sempre o mesmo valor.
Consulte a documentação do memcache para obter mais informações sobre os limites de tempo.
Um contexto totalmente novo começa com uma cache em processamento vazia.
Embora as funções de políticas sejam muito flexíveis, na prática, a maioria das políticas é simples. Por exemplo,
- Não coloque em cache entidades pertencentes a uma classe de modelo específica.
- Defina o limite de tempo limite da cache de memória para entidades nesta classe de modelo como 30 segundos.
- Não é necessário escrever entidades nesta classe de modelo no Datastore.
Para lhe poupar o trabalho de escrever e atualizar continuamente funções de políticas triviais (ou, pior, substituir as políticas para cada operação através de opções de contexto), as funções de políticas predefinidas obtêm a classe do modelo a partir da chave que lhes é transmitida e, em seguida, procuram na classe do modelo variáveis de classe específicas:
Variável de classe | Tipo | Descrição |
---|---|---|
_use_cache | bool | Especifica se as entidades devem ser armazenadas na cache no processo; substitui a política de cache no processo predefinida. |
_use_memcache | bool | Especifica se as entidades devem ser armazenadas na memcache; substitui a política de memcache predefinida. |
_use_datastore | bool | Especifica se as entidades devem ser armazenadas no Datastore; substitui a política do Datastore predefinida. |
_memcache_timeout | int | Duração total máxima para entidades na memcache; substitui a política de tempo limite da memcache predefinida. |
Nota:
esta é uma funcionalidade da função de política predefinida para cada política.
Se especificar a sua própria função de política, mas também quiser recorrer à política predefinida, chame as funções de política predefinidas explicitamente como métodos estáticos da classe Context
:
default_cache_policy(key)
default_memcache_policy(key)
default_datastore_policy(key)
default_memcache_timeout_policy(key)