Bloqueios exclusivos em itens (bloqueio pessimista)
NCache fornece um mecanismo de bloqueio pessimista que bloqueia exclusivamente os dados armazenados em cache. Este mecanismo bloqueia o item usando o identificador de bloqueio, devido ao qual todos os outros usuários são impedidos de realizar qualquer operação de gravação nesse item de cache. A LockHandle
está associado a cada item bloqueado no cache, que é retornado pela API Locking.
Note
Este recurso também está disponível em NCache Professional.
Um item bloqueado pode ser buscado/atualizado ou desbloqueado somente quando seu identificador de bloqueio é fornecido no nível da API. No entanto, você deve fazer isso com cuidado para evitar problemas de integridade de dados. O bloqueio pessimista é uma abordagem muito boa se o objetivo a ser alcançado for a consistência dos dados.
Uma vez que um bloqueio é adquirido usando LockHandle
, existem dois mecanismos para liberá-lo. Ambos os mecanismos são explicados abaixo.
Liberação de bloqueios com base no tempo: Você também pode especificar o tempo limite de bloqueio ao bloquear um item em cache. O tempo limite de bloqueio é o intervalo de tempo após o qual o bloqueio será liberado automaticamente se nenhuma chamada explícita for feita para liberação do bloqueio durante o intervalo de tempo limite. Isso evitará que seus dados sejam bloqueados por um período infinito de tempo.
Liberação forçada de bloqueios: Podem surgir situações em ambientes distribuídos quando um aplicativo que adquiriu o bloqueio em um item de cache é encerrado abruptamente ou um aplicativo finaliza seu processamento em dados bloqueados. Em tal situação, você gostaria de liberar todos os bloqueios adquiridos por tal aplicativo. NCache fornece uma API de desbloqueio, que libera o bloqueio do item de cache com força.
Note
Recomenda-se utilizar o mecanismo de bloqueio baseado em tempo para que o item seja desbloqueado após a condição ser cumprida para que os recursos permaneçam adquiridos pelo tempo mínimo.
Quando usar o bloqueio pessimista
Veja o exemplo discutido no capítulo anterior. Se a mesma conta bancária for acessada por dois usuários diferentes na mesma instância para uma operação de atualização, poderá ocorrer um conflito que levará à inconsistência de dados.
O bloqueio pessimista neste cenário permitirá que um usuário acesse a conta por vez. Ao operar com sucesso, o usuário desbloqueia o item e o controle é liberado, o que significa que o segundo usuário agora pode acessar a conta e fazer as pazes de acordo.
Usando esta abordagem, os dados permanecem consistentes e nenhum conflito ocorre.
A LockHandle
está associado a um item para garantir que o item específico permaneça inacessível em todo o cache.
NCache fornece um método que chama exclusivamente Locking, bem como inúmeras sobrecargas que manipulam o mecanismo Locking.
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: ICache, contém, Contar, inserção, Travar, Alça de bloqueio, Eliminar, Intervalo de tempo, Destravar.
Bloquear um item explicitamente
Você pode bloquear explicitamente um item antes de executar qualquer operação. Este método requer um TimeSpan
para bloquear um item por um tempo especificado. Entretanto, se você não quiser que o bloqueio adquirido expire, especifique TimeSpan.Zero
. Especificando não TimeSpan
bloqueará o item por um tempo infinito.
A Lock
método usado neste exemplo associa um LockHandle
com uma chave. Por favor, certifique-se de que o único LockHandle
está associado a uma única chave. Solte a trava antes de reutilizar a alça; caso contrário, pode levar à inconsistência de comportamento.
Se um item já estiver bloqueado, o valor falso será retornado, mas você receberá o valor atualizado LockHandle
.
Aviso
Bloqueie um item pelo mínimo TimeSpan
para evitar um impasse ou estado de fome.
O exemplo a seguir cria um LockHandle
e, em seguida, bloqueia um item com a chave Product:1001
por um período de 10 segundos, o que significa que o item será desbloqueado automaticamente após 10 segundos.
// Preconditions: Cache is already connected
// Item is already added in the cache
// Specify the key of the item
string key = $"Product:1001";
//Create a new LockHandle
LockHandle lockHandle = null;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
// Lock the item for a time span of 10 seconds
bool lockAcquired = cache.Lock(key, lockSpan, out lockHandle);
// Verify if the item is locked successfully
if (lockAcquired == true)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
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.
Bloquear um item durante a operação Get
Um item pode ser bloqueado durante sua recuperação do cache. Isso significa que o item ficará inacessível para outras pessoas, a menos que você o libere. Em caso de incompatibilidade de chaves, um valor nulo é retornado.
Se um item não estiver bloqueado e o
acquirelock
for definido como verdadeiro, você obterá o item junto com o LockHandle.Se um item estiver bloqueado e
acquirelock
é definido como falso e se você passar um LockHandle vazio incorreto ou novo, então umnull
value é retornado, mas você obterá o LockHandle que foi usado para bloquear o item anteriormente.Se um item estiver bloqueado e
acquirelock
for definido como falso e o LockHandle correto for passado, o qual foi usado anteriormente para bloquear o item, você obterá o valor.
Aviso
Bloqueie um item pelo TimeSpan mínimo para evitar conflito ou falta de thread.
Neste exemplo, uma chave e LockHandle
é especificado para buscar o objeto em cache e bloqueá-lo. Você precisa especificar true se precisar adquirir o bloqueio. Aqui o item é bloqueado com uma validade de 10 segundos, o que significa que o item será desbloqueado automaticamente após 10 segundos.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
//Create a new LockHandle
LockHandle lockHandle = null;
// Lock the item for a time span of 10 seconds
var result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Verify if the item is locked successfully
if (result != null)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
Liberar bloqueio com operação de atualização
Ao atualizar um item, você pode liberar o bloqueio permitindo que outras pessoas usem os dados armazenados em cache. Para liberar com sucesso o item bloqueado, você precisará especificar o LockHandle
inicialmente usado para bloquear o item.
A
LockHandle
deve ser o mesmo usado inicialmente para bloquear o item, caso contrário, você receberá uma mensagem de exceção dizendo "Item está bloqueado".If
releaseLock
está definido como falso, você ainda precisa passar o corretoLockhandle
para atualizar o item.Se um item não estiver bloqueado, o
LockHandle
ereleaseLock
são inúteis e são ignorados.
O exemplo a seguir bloqueia um item no cache e, em seguida, obtém o item usando o método LockHandle
. O item é então atualizado e reinserido no cache usando o inserção API.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
// Initialize the lockHandle
LockHandle lockHandle = null;
CacheItem item = cache.GetCacheItem(key, acquireLock, lockSpan, ref lockHandle);
var product = new Product();
product = item.GetValue<Product>();
// Update the unitsinstock for the product
product.UnitsInStock = 200;
bool releaseLock = true;
// Item is already locked with a LockHandle
// Update the item and release the lock as well since releaseLock is set true
// Make sure that the LockHandle matches with the already added LockHandle
cache.Insert(key, item, null, lockHandle, releaseLock);
Liberar bloqueio explicitamente
Para liberar o bloqueio explicitamente em um item armazenado em cache anteriormente bloqueado; você precisará especificar o LockHandle
inicialmente usado para bloquear o item.
Se o LockHandle
não é salvo, você também pode usar outra sobrecarga de Unlock
que só leva a chave para desbloquear o item.
Note
Se um inválido LockHandle
for passado, nenhuma exceção será lançada, mas o item permanecerá bloqueado.
O exemplo a seguir obtém um item já bloqueado usando o LockHandle
e, em seguida, desbloqueá-lo usando o Unlock
API usando o Lockhandle
salvo antes.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
//Create a new LockHandle
LockHandle lockHandle = null;
Product result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Make sure that the item is already locked and the saved LockHandle is used
// Unlock locked item using saved LockHandle
cache.Unlock(key, lockHandle);
Aviso
NCache irá ignorar os bloqueios se outras sobrecargas de Get
, Insert
e Remove
são chamados métodos que não aceitam ou usam LockHandle
.
Remover item com LockHandle
O método remove é um método básico que remove a chave do cache e retorna o objeto removido ao cliente. Se um objeto personalizado for adicionado ao cache, o método remove retornará Object.
LockHandle
deve ser o mesmo usado inicialmente para bloquear o item, caso contrário você receberá a mensagem de exceção dizendo "O item está bloqueado".Se um item não estiver bloqueado, então
LockHandle
é inútil e sua validade não é verificada.
O exemplo a seguir obtém um item que foi bloqueado anteriormente usando o LockHandle
e, em seguida, removê-lo pelo salvo LockHandle
do cache usando o Eliminar API.
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.
// Specify the key of the item
string key = $"Product:1001";
// Initialize the lockHandle
LockHandle lockHandle = null;
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
// Get the item using the lockHandle
Product result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Removing locked item using saved lockHandle.
cache.Remove(key, lockHandle);
// Check if item is successfully removed
if (result != null)
{
if (result is Product)
{
Product product = (Product)result;
}
}
Consideração especial ao usar o bloqueio de API
NCache fornece um conjunto de APIs com e sem LockHandle
para buscar/atualizar o item de cache. APIs sem LockHandle
ignore o item Bloqueio. Portanto, você deve usar todas as APIs de bloqueio para manipulação de dados. Por exemplo, se um item estiver bloqueado e você fizer uma chamada de API de atualização que não leva o LockHandle
como parâmetro de entrada, o item será atualizado no cache independentemente de seu estado de bloqueio.
importante
Ao usar um recurso de bloqueio, você só deve usar chamadas de API que levam LockHandle
como parâmetros. API que não usa identificadores de bloqueio pode ser usada, mas deve ser feita com muito cuidado para não afetar a integridade dos dados.
Note
Em caso de Despejo/Expiração, NCache ignora bloqueios, o que significa que um item bloqueado pode ser removido como resultado de expiração ou despejo.
Comportamento Sábio de Topologia
- Topologia espelhada e replicada
No Espelho Topologia, para todas as operações de bloqueio um bloqueio é adquirido no nó Ativo, e o mesmo LockHandle
é então replicado para o nó Passivo para que quando Passivo se torne Ativo, o item permaneça bloqueado. Da mesma forma, a chamada de desbloqueio também é replicada para o nó Passivo para desbloquear o item do nó Passivo.
No Replicado Topologia, o cliente está conectado a um nó, e para todas as operações de bloqueio o LockHandle
é gerado o que recebe a operação de bloqueio do cliente e, em seguida, o mesmo LockHandle
serão replicados para todos os outros nós para consistência de dados. Da mesma forma, a operação de desbloqueio também será replicada para todos os outros nós.
- Topologia Particionada e Réplica de Partição
No Particionado topologia, LockHandle
é gerado e existe no mesmo nó que contém o item e durante a transferência de estado LockHandle
as informações também são transferidas junto com o item caso o item seja movido para outro nó.
In Réplica de partição topologia, LockHandle
é gerado no nó ativo que contém o item, e o mesmo LockHandle
é então replicado para sua réplica para consistência de dados e durante a transferência de estado. LockHandle
as informações também são transferidas junto com o item caso o item seja movido para outro nó.
- Cache de cliente
No Cache de cliente, todas as operações baseadas em bloqueio são executadas diretamente no cache clusterizado, o que significa que LockHandle
é gerado e armazenado no cache clusterizado. Nenhuma informação relacionada ao bloqueio é mantida no cache do cliente.
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.