Atualmente, as empresas estão desenvolvendo aplicativos Web ASP.NET de alto tráfego que atendem a dezenas de milhares de usuários simultâneos. Vários clientes têm acesso a dados de cache em um ambiente em cluster no qual os servidores de aplicativos são implementados em um ambiente com balanceamento de carga. Em tais condições paralelas, vários usuários geralmente tentam acessar e modificar os mesmos dados e acionar uma condição de corrida.
Uma condição de corrida é quando dois ou mais usuários tentam acessar e alterar os mesmos dados compartilhados simultaneamente, mas acabam fazendo isso na ordem errada. Essa situação leva a um alto risco de perda de integridade e consistência dos dados. Com o advento das soluções de cache escalonáveis na memória, como NCache fornecendo mecanismos de bloqueio distribuídos, as empresas podem obter consistência de dados significativamente aprimorada.
NCache Adicionar ao carrinho Documentos de bloqueio e controle NCache Docs
Bloqueio distribuído para consistência de dados
NCache fornece um mecanismo de distribuição bloqueio em .NET que permite bloquear itens de cache específicos durante atualizações simultâneas. Para manter a consistência dos dados nesses casos, NCache atua como um gerenciador de bloqueio distribuído e fornece dois tipos de bloqueio:
Vamos discuti-los em detalhes mais tarde no blog. Por enquanto, considere o cenário a seguir para entender como, sem um serviço de bloqueio distribuído, há uma violação da integridade dos dados.
Dois usuários acessam a mesma Conta Bancária simultaneamente com um saldo de 30,000. Um usuário retira 15,000, enquanto o outro usuário deposita 5,000. Se feito corretamente, o saldo final deve ser de 20,000. Pelo contrário, se surgir uma condição de corrida que não seja atendida, o saldo bancário seria de 15,000 ou 35,000, como você pode ver acima.
Aqui está como essa condição de corrida ocorre:
- Tempo t1: O usuário 1 busca a conta bancária com saldo = 30,000
- Tempo t2: O usuário 2 busca a conta bancária com saldo = 30,000
- Tempo t3: O usuário 1 saca 15,000 e atualiza o saldo da conta bancária = 15,000
- Tempo t4: O usuário 2 deposita 5,000 e atualiza o saldo da conta bancária = 35,000
Em ambos os casos, um bloco de código que não atendesse ao gerenciamento de threads poderia ser desastroso para o banco. Então, nas próximas seções, vamos ver como NCache fornece mecanismos de bloqueio para garantir que a lógica do seu aplicativo seja thread-safe.
NCache Adicionar ao carrinho Bloqueio Pessimista Bloqueio Otimista
Bloqueio otimista (versões de itens)
In bloqueio otimista, NCache usos versionamento de itens de cache. No lado do servidor, cada objeto em cache tem um número de versão associado a ele que é incrementado em cada atualização de item de cache. NCache em seguida, verifica se você está trabalhando na versão mais recente. Caso contrário, ele rejeita sua atualização de cache. Dessa forma, apenas um usuário pode atualizar e outras atualizações de usuário falham.
Você pode adicionar um item no cache usando ambos Adicionar or inserção métodos.
- Add adiciona um novo item no cache e salva a versão do item pela primeira vez.
- O método insert substitui o valor de um item existente e atualiza sua versão do item.
Dê uma olhada no exemplo de código a seguir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Pre-condition: 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(); prod.UnitsInStock++; // Create a new cacheItem with updated value var updateItem = new CacheItem(prod); CacheItemVersion 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 } |
No exemplo acima, dois aplicativos diferentes usam um único cache contendo os dados dos produtos. CacheItem é adicionado ao cache. Ambos os aplicativos buscam o item com a versão atual, digamos versão. Aplicação1 modifica o Nome do Produto e, em seguida, reinsere o item no cache que atualiza a versão do item para nova versão. Application2 ainda tem o item com versão. Se application2 atualizar as unidades do item em estoque e reinserir o item no cache, a inserção do item falhará. Application2 terá, portanto, que buscar a versão atualizada para operar nesse cacheItem.
NCache Adicionar ao carrinho Bloqueio Otimista Controle de versão do item de cache
No entanto, se você deseja buscar um item existente que pode ter uma versão mais recente disponível no cache, NCache fornece uma ObterSeNovo método. Se você especificar a versão atual como um argumento da chamada do método, o cache retornará um resultado apropriado. Se a versão específica for menor que a do cache, o método retornará um novo Item, senão retornará null.
Vamos dar uma olhada no código abaixo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Get object from cache var result = cache.GetIfNewer(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 } |
O exemplo acima adiciona um item no cache com a chave Product:1001 e a versão do item. Se alguma versão mais recente do item estiver disponível, ObterSeNovo O método busca o item usando a versão do item de cache.
Com bloqueio otimista, NCache garante que cada gravação no cache distribuído seja consistente com a versão que cada aplicativo contém. Por favor consulte o nosso oficial NCache Documentação para um exemplo de código extenso.
NCache Adicionar ao carrinho ObterSeNovo CacheItemVersionamento
Bloqueio Pessimista (Bloqueio Exclusivo)
A outra maneira de garantir a consistência dos dados é adquirir um bloqueio exclusivo nos dados armazenados em cache. Esse mecanismo é chamado Bloqueio pessimista . Ele bloqueia o item usando o identificador de bloqueio, bloqueando todos os outros usuários de realizar qualquer operação de gravação nesse item de cache. UMA Alça de bloqueio é um identificador associado a cada item bloqueado no cache retornado pela API de bloqueio.
O exemplo a seguir cria um LockHandle e bloqueia um item com a chave Product:1001 por um período de 10 segundos para que o item seja desbloqueado automaticamente após 10 segundos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Pre-Requisite: 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 } |
Ao adquirir o bloqueio com sucesso ao buscar o item, o aplicativo agora pode executar operações com segurança, sabendo que nenhum outro aplicativo pode obter ou atualizar esse item enquanto você tiver esse bloqueio. Chamaremos a API Insert com o mesmo identificador de bloqueio para atualizar os dados e liberar o bloqueio. Fazer isso inserirá os dados no cache e liberará o bloqueio, tudo em uma chamada, permitindo que os dados armazenados em cache estejam disponíveis para todos os outros aplicativos.
Apenas lembre-se de que você deve adquirir todos os bloqueios com um tempo limite. Por padrão, se o tempo limite não for especificado, NCache bloqueará o item por um período de tempo indefinido, intervalo de tempo.zero. Pode haver um caso em que o item pode permanecer bloqueado para sempre se o aplicativo travar sem liberar o bloqueio. Para uma solução alternativa, você pode liberar com força mas esta prática é desaconselhada. Portanto, bloqueie um item pelo TimeSpan mínimo para evitar deadlock ou inanição de thread.
NCache Adicionar ao carrinho Bloqueio Pessimista Usando Bloqueio com Bloqueio de Dados em Cache
Suporte Failover em Bloqueio Distribuído
Como NCache é uma memória, cache distribuído, ele também fornece suporte completo a failover para que não haja perda de dados e seja altamente disponível. Em caso de falha do servidor, seus aplicativos clientes continuam funcionando perfeitamente. Da mesma forma, seus bloqueios no sistema distribuído também são replicados e mantidos pelos nós de replicação. Se algum nó falhar enquanto um de seus aplicativos adquirir um bloqueio, ele será propagado para um novo nó automaticamente com suas propriedades especificadas, por exemplo, Vencimento do bloqueio.
Conclusão
Então, qual mecanismo de bloqueio é melhor para você, otimista ou pessimista? Bem, depende do seu caso de uso e do que você deseja alcançar. O Bloqueio Otimista oferece um benefício de desempenho aprimorado em relação ao Bloqueio Pessimista, especialmente quando seus aplicativos exigem muita leitura. Considerando que, o bloqueio pessimista é mais seguro do ponto de vista da consistência dos dados. Portanto, escolha seu mecanismo de travamento com cuidado. Para mais detalhes, acesse o site do Network Development Group. Em caso de dúvidas, Contacte-nos e deixe que nossos especialistas o ajudem!
NCache Adicionar ao carrinho Baixar NCache Comparação de edições