Bloqueio com controle de versão de item de cache (bloqueio otimista)
Enquanto Bloqueio Pessimista é uma abordagem muito útil, há uma limitação envolvida em seu uso, um item não pode ser usado a menos que pelo menos uma operação seja executada completamente nele. Isso significa que o item permanece bloqueado até que uma tarefa seja executada completamente no item. Isso pode causar falta de thread se um item permanecer bloqueado por muito tempo.
Note
Este recurso também está disponível em NCache Professional.
É aqui que o Optimistic Locking se torna útil, pois NCache usa versionamento de itens de cache. CacheItemVersion
é uma propriedade associada a cada item de cache. É um valor numérico que representa a versão do item armazenado em cache, que se incrementa em um a cada atualização de um item. Esta propriedade permite acompanhar se ocorre alguma alteração em um item ou não. Ao buscar um item do cache, você também busca sua versão atual no cache.
Para aplicativos de leitura intensiva, o Bloqueio Otimista é preferível ao Bloqueio Pessimista.
Quando usar o bloqueio otimista
No exemplo anterior, tínhamos uma única conta bancária utilizada por dois usuários simultaneamente. Suponhamos que um dos usuários adquiriu o bloqueio para realizar uma transação de depósito na conta bancária. O Usuário2 está aguardando o Usuário1 liberar o bloqueio para ele realizar a transação de saque. Considere que o Usuário1 entra em um estado instável devido a problemas de conectividade de rede sem liberar o bloqueio. O usuário2 fica esperando que ele libere o bloqueio sem o conhecimento de quaisquer problemas de conectividade, então ele entra em estado de inanição até que o primeiro usuário libere o bloqueio.
Para evitar esse tipo de problema, o Optimistic Locking é uma solução útil. Usando este tipo de bloqueio, se o Usuário1 quiser atualizar a conta, ele poderá atualizar a conta sem bloqueá-la e a versão do item será atualizada de acordo. Agora, quando o Usuário2 quiser atualizar os dados, ele obterá a versão atualizada com base na versão do item e isso garantirá que nenhum problema de integridade dos dados ocorra. Se algum usuário operar nos dados com a versão antiga do item, a operação falhará considerando que possui uma versão desatualizada do item.
CacheItemVersion
adiciona uma dimensão adicional ao desenvolvimento da aplicação usando NCache. A simultaneidade otimista pode ser alcançada em aplicativos por NCache Versionamento de itens.
Quando qualquer item é adicionado ao cache, a versão do item de cache retorna ao cliente de cache. Este valor denota o número de atualizações realizadas em dados específicos. A cada atualização, o valor da versão do item aumenta.
Pré-requisitos
- Para aprender sobre os pré-requisitos padrão necessários para trabalhar com todos os NCache recursos do lado do cliente, consulte a página fornecida em Pré-requisitos da API do lado do cliente.
- Para obter detalhes da API, consulte: Adicionar, ICache, Item de cache, CacheItemVersão, contém, Contar, ObterSeNovo, inserção, Eliminar.
Recuperar e atualizar o item com a versão do item
An Adicionar operação retorna o CacheItemVersion
. Se um item for adicionado pela primeira vez, será retornado um valor longo contendo o TimeStamp de sua criação. Esta versão será incrementada em "1" ao realizar operações nesta chave no futuro.
O bloqueio otimista garante que o usuário sempre obtenha a cópia mais atualizada do item do cache. Se o usuário continuar executando funções na versão desatualizada, NCache lança uma exceção, para que o usuário obtenha o item atualizado do cache.
No exemplo abaixo, um cache é usado por vários aplicativos. O cache contém os dados dos produtos. UMA CacheItem
é adicionado ao cache. Ambos os aplicativos buscam o item com a versão atual, digamos versão. Application1 modifica o Nome do Produto e reinsere o item no cache, o que atualiza a versão do item para a nova versão. O aplicativo 2 ainda possui o item com a versão. Se a Aplicação2 atualizar as unidades do item em estoque e reinserir o item no cache, a inserção falhará. Application2 terá que buscar a versão atualizada para realizar a operação, nesse caso CacheItem
.
Note
Você pode adicionar um item no cache usando ambos Adicionar or inserção métodos.
- A
Add
O método adiciona um novo item ao cache e salva a versão do item pela primeira vez. - A
Insert
O método adiciona um item no cache, se ainda não estiver presente, enquanto substitui o valor de uma hora existente e atualiza a versão do item.
As seções de código a seguir explicam as operações executadas pelo aplicativo.
// Precondition: Cache is already connected
// An item is added in the cache with itemVersion
// Specify the key of the cacheItem
string key = "Product:1001";
// Initialize the cacheItemVersion
CacheItemVersion version = null;
// Get the cacheItem previously added in the cache with the version
CacheItem cacheItem = cache.GetCacheItem(key, ref version);
// If result is not null
if (cacheitem != null)
{
// CacheItem is retrieved successfully with the version
// If result is Product type
var prod = new Product();
prod = cacheItem.GetValue<Product>();
prod.UnitsInStock++;
// Create a new cacheItem with updated value
var updateItem = new CacheItem(prod);
//Set the itemversion. This version will be used to compare the
// item version of cached item
updateItem.Version = version;
cache.Insert(key, updateItem);
// If it matches, the insert will be successful, otherwise it will fail
}
else
{
// Item could not be retrieved due to outdated CacheItemVersion
}
Note
Para garantir que a operação seja à prova de falhas, é recomendável lidar com possíveis exceções em seu aplicativo, conforme explicado em Como lidar com falhas.
Recuperar o item se existir uma versão mais recente no cache
A GetIfNewer
O método pode ser usado para buscar o item existente se uma versão mais recente estiver disponível no cache. Ao especificar a versão atual como argumento da chamada do método, o cache retorna o resultado apropriado.
Se a versão especificada for menor que a que está no cache, só então o método retornará um novo Item else nulo será retornado.
O exemplo a seguir adiciona um item no cache com a chave Product:1001
e a versão do item e, em seguida, recupera-o se alguma versão mais recente estiver disponível usando o GetIfNewer
método que busca um item usando a versão do item de cache.
// Get updated product from database against given product ID
Product product = FetchProductByProductID(1001);
// Generate a unique key for this item
string key = $"Product:{product.ProductID}";
// Create a new CacheItem
var item = new CacheItem(product);
// Add CacheItem to cache with new itemversion
CacheItemVersion version = cache.Insert(key, item);
// Get object from cache
var result = cache.GetIfNewer<Product>(key, ref version);
// Check if updated item is available
if (result != null)
{
// An item with newer version is available
if (result is Product)
{
// Perform operations according to business logic
}
}
else
{
// No new itemVersion is available
}
Remover item com versão do item
Um item pode ser removido do cache usando uma sobrecarga de Eliminar, com base na versão do item. No entanto, se a versão do item for diferente daquela no cache, você obterá uma exceção especificando isso.
O exemplo a seguir mostra como remover um item do cache especificando a versão do item usando o Eliminar método.
Dica
Você pode monitorar/verificar a remoção:
- Contador de "contagem de cache" em NCache Monitore or Contadores PerfMon.
- utilização
cache.Contains
após o intervalo de expiração ter decorrido. - utilização
cache.Count
antes e depois de especificar a expiração.
// Get updated product from database against given product ID
Product product = FetchProductByProductID(1001);
// Cache key remains the same for this product
string key = $"Product:{product.ProductID}";
// Create a new CacheItem
var item = new CacheItem(product);
// Insert CacheItem to cache with new itemversion
CacheItemVersion version = cache.Insert(key, item);
// Remove the item from the cache using the itemVersion
cache.Remove(key, null, version);
Comportamento Sábio de Topologia
- Para o espelho e o cache replicado
No Espelho Topologia, quando um item é adicionado ou atualizado, sua versão é gerada no nó Ativo e a mesma versão é então replicada para o nó Passivo junto com o item para que quando um nó ativo se torne passivo, a versão do item permaneça a mesma.
No Replicado Topologia: o cliente está conectado a um nó e a versão do item é gerada em um nó que recebe a operação de atualização/adição do cliente e, em seguida, a mesma versão do item junto com o item é replicada para todos os outros nós para consistência de dados.
- Para o cache particionado e de réplica de partição
No Particionado Topologia, a versão do item é gerada e existe no mesmo nó que contém o item, e durante a transferência de estado a versão também é transferida junto com o item caso o item seja movido para outro nó.
No Réplica de partição Topologia, a versão é gerada no nó ativo, que contém o item e a mesma versão junto com o item é então replicada para sua réplica para consistência de dados e durante a transferência de estado a versão também é transferida junto com o item caso o item seja movido para outro nó.
- Cache de cliente
No Cache de cliente, todas as informações relacionadas à versão são mantidas no cache clusterizado e sempre que uma API relacionada à versão é chamada, o usuário obtém sua versão do cache clusterizado.
Recursos adicionais
NCache fornece um aplicativo de exemplo para o item Locking on GitHub.
Veja também
.INTERNET: Alachisoft.NCache.Runtime.Cache espaço para nome.
Java: com.alachisoft.ncache.runtime.caching espaço para nome.
Node.js: Esconderijo classe.
Pitão: ncache.runtime.caching classe.