Sul da Flórida Code Camp 2017

Dimensionamento de aplicativos .NET com cache distribuído

Por Iqbal Khan
Presidente e Evangelista de Tecnologia

Seus aplicativos .NET podem enfrentar gargalos de banco de dados ou armazenamento devido ao crescimento na carga de transações. Saiba como remover gargalos e dimensionar seus aplicativos .NET usando cache distribuído. Esta conversa abrange:

  • Visão geral rápida dos gargalos de escalabilidade em aplicativos .NET
  • Descrição do cache distribuído e como ele resolve problemas de desempenho
  • Onde você pode usar o cache distribuído em seus aplicativos
  • Alguns recursos importantes em um cache distribuído
  • Exemplos práticos usando um cache distribuído

Hoje vou falar sobre como você pode dimensionar aplicativos .NET com cache distribuído. Esta conversa não é sobre NCache. Embora eu me refira NCache mas o objetivo principal é educá-lo sobre quais são os problemas e como você pode resolvê-los com o armazenamento em cache.

O que é Escalabilidade

Ok! Apenas para fins de completude, vamos passar por algumas das definições que tenho certeza que você já as conhece, mas vamos primeiro definir o que é escalabilidade. Escalabilidade não é alto desempenho. Alto desempenho seria algo se você tivesse cinco usuários, você tem um tempo de resposta muito bom, isso é um alto desempenho. Escalabilidade é se você puder manter o mesmo alto desempenho sob cargas de pico. Portanto, se seu aplicativo não tiver alto desempenho com cinco usuários, você terá outros problemas. Mais do que podemos resolver lá.

Escalabilidade Linear

Em segundo lugar, o que é escalabilidade linear. A escalabilidade linear é mais uma definição de implantação.

escalabilidade linear

Quando você implanta seu aplicativo em um ambiente de vários servidores, digamos, se você tiver um ambiente com balanceamento de carga, seu aplicativo será linearmente escalável se você puder simplesmente adicionar mais servidores para obter capacidade de transação adicional. Então, se você tivesse mil usuários com dois servidores, você teria um terceiro servidor, digamos, 1500 usuários e então, à medida que você adiciona mais servidores, você obtém 500 usuários cada. Estou apenas dizendo hipoteticamente, mas isso é uma escalabilidade linear. Se você pode alcançar isso, então esse é o objetivo, porque então você nunca se depara com problemas, para os quais tenho certeza que você estava aqui para resolver.

Escalabilidade não linear

A escalabilidade não linear é exatamente o oposto do que é que você tem uma arquitetura de aplicativo onde você simplesmente não pode comprar hardware mais caro ou mais servidores para resolver esse problema.

escalabilidade não linear

Você tem alguns gargalos fundamentais, então, à medida que você adiciona mais servidores, seu aplicativo, por um certo tempo, o desempenho ou a capacidade de transação aumenta, mas depois disso ele fica mais lento, mesmo que você adicione mais servidores. Então, você definitivamente não quer escalabilidade não linear.

Que tipo de aplicativos precisam de escalabilidade?

Geralmente, são aplicativos do lado do servidor.

aplicativos-necessidade-escalabilidade

Esses são aplicativos da Web, ASP.NET, podem ser serviços da Web WCF, podem ser o back-end para qualquer aplicativo IOT. Temos muitos dispositivos IOT diferentes conversando com algum tipo de back-end. Isso pode ser aplicativos de processamento de big data, embora o processamento de big data seja mais uma atividade Java. Por causa do Hadoop, o .NET não é um processamento de big data muito grande, mas se você estivesse fazendo processamento de big data, você definitivamente precisaria dimensionar e qualquer outro aplicativo de servidor que não se encaixasse nessa categoria. Quer dizer, você pode ter muito processamento em lote, se você é uma grande corporação, você pode ter que atualizar um certo número de coisas até meia-noite ou antes do próximo dia útil e, à medida que você tem mais e mais clientes, você tem milhões e milhões de clientes, você, é claro, precisa escalar isso.

Portanto, mesmo nesses aplicativos de back-end, um bom exemplo pode ser que os clientes estejam, seu banco e os clientes estejam transferindo fundos de uma conta para outra, que geralmente é processado no back-end em modo de lote à noite. Então, você tem que contratualmente fazer isso dentro de um determinado período de tempo. Então, todas essas aplicações, se não tiverem escalabilidade, você tem grandes problemas.

Qual é o problema de escalabilidade?

Felizmente, a camada do aplicativo não é onde está o problema. Se você tiver a maioria desses aplicativos, na camada de aplicativos você pode adicionar mais servidores, não há grande problema. É o armazenamento de dados que é o problema. E, quando uso a palavra armazenamento de dados, quero dizer bancos de dados relacionais, dados legados de mainframe. É onde reside a maioria dos seus dados e são eles que não podem escalar da mesma forma que os aplicativos. Agora, NoSQL databases existem para um dos casos de uso é dimensionar, mas, o problema com NoSQL databases, e novamente, temos um NoSQL database do nosso chamado NosDB. É um banco de dados de código aberto. Assim, a limitação de NoSQL database é que você simplesmente não pode mover todos os dados para ele porque eles exigem que você mova os dados para fora do seu mainframe ou de seus bancos de dados relacionais, o que por vários motivos, talvez técnicos, talvez comerciais, talvez você não consiga fazer.

Assim, os bancos de dados relacionais continuarão sendo sua principal fonte de dados mestre. Há muitos casos de uso em que você pode colocar muitos dos novos dados em NoSQL databases e quando você faz isso, eles resolvem o gargalo de escalabilidade. Mas, na maioria dos casos, você só pode fazer isso para um subconjunto de seus dados. A maioria dos dados ainda precisa permanecer em seus bancos de dados relacionais ou em suas fontes de dados de mainframe legadas. Então, qualquer que seja o problema que você tenha que resolver, essa escalabilidade, você tem que resolvê-lo enquanto continua trabalhando com bancos de dados relacionais ou com seu mainframe legado. E é aí que um cache distribuído realmente resolve esse problema. Ele permite que você continue usando seus dados de mainframe de bancos de dados relacionais enquanto remove todo esse gargalo.

Implantação de cache distribuído

Então, aqui está uma imagem, se você tivesse, se esses são seus dados legados de bancos de dados relacionais, você pode colocar uma camada de cache entre o aplicativo e o banco de dados.

implantação de cache distribuído

Quando você faz isso, você começa a armazenar em cache os dados que usará com frequência. E, em cerca de 80% do tempo, você nem precisa acessar o banco de dados. E, o cache, por ser um cache distribuído, você pode adicionar mais e mais servidores, ele é dimensionado da mesma forma que a camada do aplicativo. Portanto, você tem um mínimo de dois servidores de cache aqui e, em seguida, mantém uma proporção de quatro para um ou cinco para um entre a camada de aplicativo e a camada de armazenamento em cache. Agora, essa proporção pode mudar dependendo da natureza de suas operações. Se cada um de seus, digamos, você tivesse um aplicativo da web, para cada clique de usuário, você fizesse centenas de chamadas de cache, então, é claro, a proporção mudaria, mas, na maioria das vezes, você não faz centenas de chamadas de cache.

Um servidor de cache típico é apenas um servidor de baixo custo. É um tipo de configuração de servidor web, CPU dupla, tipo quad-core de uma caixa, ele tem muita memória. Muita memória significa que 16 a 32 giga é bastante padrão, mais de 32 giga você normalmente não tem que fazer. Embora tenhamos muitos clientes que vão até 64 GB, recomendamos que, em vez de ter muito mais memória em cada caixa, adicione mais caixas. E, a razão é porque quanto mais memória você tem em cada caixa, mais processador poderoso você precisa ter e então sua caixa está começando a parecer cada vez mais com um banco de dados que não é a intenção. Você quer manter isso tão baixo custo quanto possível.

Agora, um cache distribuído é uma infraestrutura que você deseja colocar para todos os seus aplicativos. Assim, assim como você tem um banco de dados que é praticamente uma infraestrutura comum, a nova prática recomendada é ter um cache distribuído na memória. Também é chamado de in-memory NoSQL armazenamento de valor-chave. E tenha isso como parte de seus aplicativos de infraestrutura e arquitetura para que você sempre vá a esta loja. Então, você verifica a loja antes de ir para o banco de dados. Depois de ter essa infraestrutura, todos os seus aplicativos se tornam automaticamente escaláveis. Assim, você nunca precisa se preocupar com os bancos de dados se tornando um gargalo. E, o maior problema com escalabilidade ou não ser capaz de escalar é que é quando sua empresa está fazendo muita atividade.

Digamos que você seja uma companhia aérea e acabou de fazer uma promoção especial para o Havaí. Todo mundo está acessando seu site na, sei lá, quarta-feira para começar a comprar ingressos. Então, eles vão procurar voos e comprar passagens e, você tem cinco vezes mais tráfego do que antes e de repente o site fica mais lento, talvez ele trave e pode travar, é claro , se seu banco de dados ficar sobrecarregado, mas, mesmo que ele fique lento além dos limites aceitáveis, seu custo para o negócio será muito alto porque as pessoas simplesmente sairão. Então, você realmente precisa ter certeza de que planeja escalabilidade para que nunca tenha aquela situação em que sua empresa deseja fazer mais atividades, eles são capazes de gerar negócios, mas você não consegue processar dentro do aplicativo. E, se você tiver a infraestrutura certa, nunca terá esse problema.

Estou apenas configurando o caso de por que você deve usar um cache distribuído? Qual problema é resolvido e, em seguida, entraremos em detalhes de como você realmente o usa. Além de ter mais memória, normalmente você tem, como eu disse, dual CPU, configuração quad core, 2 placas de rede de um gigabit ou mais cada. No caso de NCache são caixas do Windows, no caso de Redis estas são caixas Linux, dependendo se você tem um aplicativo .NET ou Java. Meu foco aqui é .NET, mas para Java você também tem caches distribuídos. Eles os chamam de grade de dados na memória, no lado .NET é chamado de cache distribuído.

Casos de uso comuns de cache distribuído

Ok! Portanto, agora que criamos o caso sobre por que você precisa ter o cache distribuído como parte de sua infraestrutura de práticas recomendadas, tanto do ponto de vista de TI quanto, mais importante, do ponto de vista do desenvolvimento, você deseja arquitetar o aplicativo. A primeira pergunta que me vem à mente também, como eu uso essa cache? Quais são os casos de uso? Onde eu os uso? Quer dizer, eu sei que tipo de aplicativos vou usá-los, mas que tipo de dados vou armazenar em cache?

usecases

Portanto, existem três categorias principais. O número um é o que todos entendem que é o cache de dados do aplicativo.

Cache de dados do aplicativo

Então, no cache de dados de aplicativos, você está armazenando em cache os dados que existem em seu banco de dados, você os está armazenando em cache, é sobre isso que acabamos de falar. Então, quando você faz isso, na verdade está criando duas cópias dos dados. Um está no banco de dados para o mestre e um está no cache que é a cópia temporária. Quando isso acontece, qual é a principal preocupação? O que poderia dar errado quando você tem duas cópias? Eles podem ficar fora de sincronia. Na verdade, esse é um medo tão grande na mente das pessoas que a maioria das pessoas quando você pergunta para que você usa o cache, elas dizem bem para dados somente leitura, eu não posso me arriscar com meus dados transacionais, com dados que muda porque e se isso der errado. E se meu cliente retirar esse dinheiro duas vezes da mesma conta, o que acontecerá?

Bem, se você não puder armazenar dados transacionais em cache, o valor de um cache distribuído diminuirá um pouco porque os dados de referência são apenas vinte por cento ou trinta por cento dos dados. 80 por cento ou 70 a 80 por cento dos dados são seus clientes, suas contas, as atividades, seus dados transacionais, os dados que mudam a cada 30 segundos, a cada minuto, dados que você pode manter no cache por um tempo muito muito curto. Portanto, se você não puder usar um cache para dados transacionais, você realmente se restringiu. Portanto, um bom cache distribuído deve garantir que o cache e o banco de dados estejam sempre sincronizados. Para que, uma vez que você tenha esse conforto, a tranquilidade de que o cache está sempre sincronizado com o banco de dados, você pode armazenar em cache praticamente tudo e, quando faz isso, realmente vê muitos jogos.

E, eu vou entrar em muito mais detalhes sobre isso.

Cache específico do ASP.NET

O segundo caso de uso é quando você tem um aplicativo ASP.NET, há certas coisas específicas do ASP.NET que você pode armazenar em cache. E, o bom desta categoria é que não há necessidade de programação de sua parte porque a Microsoft tem uma estrutura onde um cache será apenas plugado. O número um é o estado da sessão. Todo aplicativo ASP.NET precisa ter um estado de sessão, praticamente. Algumas pessoas programaram especialmente para não usá-lo, o que não é uma boa ideia. Você deve usar uma sessão torna sua vida muito mais fácil.

Uma sessão é um candidato muito bom para armazenamento em cache porque se você armazenar uma sessão no banco de dados, terá os mesmos problemas que os bancos de dados não são projetados para armazenar blobs, que é o que é uma sessão. Então, o desempenho é muito lento e, mais importante, a escalabilidade simplesmente desaparece. Pelo mesmo motivo que você deseja fazer o cache de dados do aplicativo, você deseja colocar as sessões também não no banco de dados. Você deseja colocá-los no cache distribuído.

O segundo é um estado de visualização. Se você não estiver usando o framework MVC, se ainda estiver no ASP antigo.NET framework então veja o estado. Para aqueles que não sabem o que é um estado de visualização, um estado de visualização é uma string criptografada que pode ter apenas cem bytes ou centenas de kilobytes que são gerados e enviados ao navegador apenas para voltar quando você faz um post de volta. Então, é uma viagem bem cara. Isso, é claro, diminui seu desempenho porque muito mais dados estão sendo enviados. E, também aumenta seus custos de largura de banda, porque quando você hospeda seu aplicativo, o canal acima não é gratuito. Assim, quando seus clientes acessam seu aplicativo da Web, você está pagando pela largura de banda aqui. Portanto, um estado de exibição, quando você multiplica isso pelos milhões e milhões de solicitações ou pelas transações que seus usuários ou clientes farão, há muito custo extra que você não deseja incorrer. Então, esse é um candidato muito bom para armazenamento em cache. Então, você armazenou em cache no servidor e apenas envia uma pequena chave que na próxima vez que ocorrer um post ruim, a chave volta e antes que a página seja executada, o estado de exibição é obtido do cache.

O terceiro é o cache de saída que é outra parte do ASP.NET framework que se a saída da sua página não está mudando, por que executá-la da próxima vez? Porque toda vez que você executar a página, ela consumirá CPU, memória e todos os outros recursos, incluindo seus bancos de dados. Então, é muito melhor apenas retornar a saída da última execução que pode ser a página inteira ou pode ser parte da página. Portanto, para todos esses três, basta conectar um cache distribuído sem nenhuma programação. Agora eu vou te mostrar isso. Mas, a natureza deste problema é muito diferente da aplicação.

Nos dados do aplicativo tínhamos duas cópias dos dados, certo? Então, o problema era a sincronização. Aqui, você tem apenas uma cópia e está sendo mantida em um armazenamento na memória. Então, qual é a maior preocupação quando você mantém algo assim em uma loja na memória e essa é a única cópia. Isso também! Ou, se algum servidor cair, você acabou de perder esse cache. Então, para que isso seja armazenado no cache. Imagine a mesma companhia aérea pela qual acabei de passar e passei meia hora encontrando a combinação perfeita de companhia aérea e estou prestes a clicar em enviar e a sessão está perdida, não é uma boa experiência porque o servidor da web acabou de cair.

Então, para isso, como você resolve esse problema quando você tem um in-memory e tem essa preocupação? Você tem redundância. Você tem mais de uma cópia dos dados. Portanto, um bom cache distribuído deve permitir a replicação de dados. Sem replicação de dados de forma inteligente e de alto desempenho, seu cache novamente se torna muito menos útil.

Compartilhamento de dados de tempo de execução por meio de eventos

O terceiro caso de uso é algo que a maioria das pessoas não conhece ou está começando a se tornar mais popular é que você pode usar, você tem essa infraestrutura na memória muito escalável. Você pode usá-lo para compartilhamento de dados em tempo de execução por meio de eventos, ele diz como uma mensagem, mas uma versão muito simplificada e está em um único tipo de centro de dados de um ambiente onde você pode ter vários aplicativos usando o cache como uma maneira de fazer Tipo Pub/Sub de um compartilhamento de dados. Então, um aplicativo coloca algo no cache, dispara um evento e os consumidores que estão interessados ​​nesses dados recebem esse evento e podem consumir esses dados.

Então, em vez de colocar isso no banco de dados ou colocar isso em um tipo de fila MSM de uma situação que tem seu próprio propósito. Um cache não existe para substituir a fila do MSM, mas, em muitas situações, é uma infraestrutura muito mais simples e especialmente muito mais rápida e escalável para fazer o compartilhamento de dados baseado em eventos. Então, se você tem uma necessidade onde você tem vários aplicativos que precisam compartilhar dados uns com os outros em tempo de execução, então você definitivamente deve considerar isso como um recurso, um recurso muito importante.

Cache específico do ASP.NET

Vou apenas mostrar rapidamente o cache do ASP.NET, como você faz isso. É muito, muito simples e eu vou realmente usar… Então, eu tenho um código de exemplo. Então, por exemplo, se eu fosse... Então, eu tenho esse aplicativo ASP.NET. Tudo o que você precisa fazer é acessar o web.config, no caso de NCache e novamente será praticamente o mesmo para todos os caches. A primeira coisa que você precisa fazer é adicionar um assembly. Portanto, esse assembly é o provedor de estado da sessão. Então, ASP.NET framework tem uma interface de provedor de estado de sessão que um cache distribuído precisa implementar. NCache implementou e isso carrega o assembly em seu aplicativo.

Então, depois de fazer isso, a próxima coisa que você precisa fazer é ir para a tag de estado da sessão. Na verdade, e certifique-se de que o modo é personalizado e o tempo limite, certifique-se de que seja o que o tempo limite quiser. No caso de NCache então é só colocar essa linha. Outros caches possuem um tipo de informação semelhante. Então, você só tem .. Em caso de NCache tudo o que você precisa fazer é certificar-se de que seu cache está nomeado e eu realmente mostrarei o que isso significa. Mas, com apenas essa mudança em seu aplicativo, você pode basicamente começar a armazenar suas sessões. Então, você faz essa alteração em cada web.config na camada do aplicativo, é claro, certifica-se de que existe um cache. E então, depois de fazer isso, você pode realmente começar a colocar sessões no cache.

Demonstração prática

Vou mostrar rapidamente um cluster de cache. Então, por exemplo, eu tenho essas... uh, eu tenho essas VMs do Azure onde eu tenho demo1 e demo2, assim como minhas VMs de servidor de cache e o cliente de demonstração é como o servidor de aplicativos. Então, esses são os clientes. Um cliente de cache é sua caixa de servidor de aplicativos. Então, eu vou…

Criar um cluster de cache

E, eu entrei, digamos, entrei no cliente de demonstração e vou usar isso, no caso de NCache e novamente vou usar essa ferramenta chamada NCache Gerente. É uma ferramenta gráfica. Vamos configurar os caches a partir de um único local. Eu virei aqui e direi criar um novo cache clusterizado. Todos os caches são nomeados em NCache. Então, vou nomear meu cache como cache de demonstração. Não vou entrar em nenhum dos detalhes dessas propriedades.

Vou escolher minha estratégia de replicação para ser uma réplica particionada. E, vou escolher uma replicação assíncrona. Eu faço meu primeiro servidor de cache. Vou fazer meu segundo servidor de cache aqui. Então, vou construir um cluster de cache de dois nós. Eu só vou pegar tudo. Então, essa é a porta TCP na qual o cluster de cache é formado, você pode alterá-la se houver um conflito de porta. Vou especificar quanta memória meu servidor de cache usará para cache. Eu tenho isso como um show, é claro, o seu vai ser muito mais.

Então, por exemplo, aqui deixe-me mostrar rapidamente o que isso significa. Vou apenas para esta parte.

topologia de cache

Então, pense nisso como um servidor de cache e isso tem outro servidor de cache. Portanto, a partição 1 existe aqui. A partição 1 é essencialmente uma coleção de buckets. A partição 2 tem sua própria caixa. Então, há um caso de NCache são cerca de mil buckets que são distribuídos entre quantas partições você tem. Cada servidor tem uma partição e cada servidor a partição é replicada em um servidor diferente. Portanto, se você tiver três servidores, verá que o backup da partição 1 foi feito aqui. A partição 2 é copiada aqui. A partição 3 é copiada aqui. As réplicas não estão ativas em caso de NCache. Eles se tornam ativos somente se a partição principal ficar inativa.

Então, o que estou especificando é o tamanho de uma partição. Portanto, no caso de réplica de partição, se eu especificar, digamos, 1 giga aqui, na verdade usará 1 giga para a partição e 1 giga para a réplica. Então, um total de 2 shows. Então, se você tem, digamos, 16 GB de memória, o que você quer fazer é deixar cerca de dois ou dois GB e meio para o sistema operacional e outros processos e o resto você pode usar. Então, para 16 shows você pode facilmente usar 13 shows. Então, faça um meio e meio. Então, é um tamanho de partição de seis e meio GB e, é claro, você pode ter 32 GB e novamente você deixa três GB de fora e você tem 29 GB e meio, 14 GB e meio tamanho de partição. E, então, como você deseja mais armazenamento, em vez de adicionar mais memória apenas para adicionar mais servidores, porque é mais fácil de gerenciar. Mantém as coisas muito mais escaláveis. Então, eu vou apenas bater próximo aqui.

A próxima é a minha política de despejo. Não vou entrar nesses detalhes. E agora vou adicionar o nó do cliente. Depois de fazer isso, vou iniciar um cache. Vou começar um cache e queria mostrar essa parte para vocês porque é isso que vai fazer sentido no resto da palestra. Então, está iniciando esses dois nós de cache.

Simule o estresse e monitore as estatísticas de cache

Então, vou abrir um monte de ferramentas de monitoramento e vou realmente executar essa ferramenta chamada ferramenta de teste de estresse.

ferramenta de teste de estresse

É uma linha de comando. É um console que realmente começa a fazer atividade no cache. Agora, é como se estivesse simulando seu aplicativo. Então, se você olhar para ele, seu aplicativo está colocando sessões no cache, cada sessão é um objeto. Então, você está adicionando. Então, a contagem de cache ficou 177, nesta caixa 172 e 35. Então, vai ser quase igual e então é melhor fazer backup em um diferente…

estatísticas pós-estresse

Este é feito o backup aqui, este é o backup aqui. Então, como você pode ver, a replicação está acontecendo automaticamente. Seu aplicativo não precisa se preocupar. Tudo que você fez foi criar este cluster e na camada de aplicação você apenas modificou o Web.config e todo o resto acontece automaticamente. Você pode, é claro, monitorar essas coisas, mas o cache é nomeado. Então, no nosso caso, nomeei o cache como cache de demonstração. Você pode nomeá-lo, na verdade, você pode ter vários caches. A configuração mais comum que vimos com nossos clientes é que eles têm três caches. Um cache eles vão chamá-lo, digamos, cache de objetos. Então, é o seu principal cache transacional. Um cache eles chamarão de cache de sessão. Então, ele colocará todas as sessões nesse cache. O terceiro cache eles chamarão de cache de referência. Assim, eles colocarão mais dados de referência no cache de referência.

E, a razão pela qual eles criam um cache separado para dados transacionais versus os dados de referência é porque, para dados de referência, você deseja usar esse recurso chamado Cache do cliente, no qual deseja armazenar em cache.

Cache de cliente para um desempenho ainda melhor

Na verdade, estou pulando, então, por favor, me perdoe se estou confundindo as coisas. Se você tiver dados de referência, na verdade, deixe-me voltar mais um. antes de ter caches distribuídos, as pessoas tinham isso, objeto de cache ASP.NET. O objeto de cache ASP.NET era um cache InProc local. Foi dentro do processo de inscrição, super rápido, né? Se você está mantendo coisas em sua própria pilha, nada pode igualar esse desempenho. Assim que você entra em um cache distribuído, é diferente, é um cache de processo automático. O que as pessoas não percebem é que seu desempenho realmente cai.

Temos muitos clientes que inicialmente ficaram confusos e disseram, bem, eu deveria obter um aumento de desempenho e meu desempenho caiu de um cache ASP.NET lá em cima está muito mais lento agora, porque eles precisam serializar o objeto. Se você tiver um objeto grande, a serialização é um custo bastante significativo e esse é um custo que você deve incorrer independentemente de qualquer cache específico. E, assim que você sai do cache de processo, seu desempenho é muito mais lento do que um cache InProc local. Mas, ainda é mais rápido que o banco de dados. É quase 10 vezes mais rápido que o banco de dados, mas quase você pode dizer 10 vezes mais lento que o cache InProc.

Então, o que acontece é que as pessoas querem ganhar esse benefício desse cache InProc. Bem, para dados que não mudam com muita frequência, existe um recurso chamado Client Cache. Algumas pessoas chamam de Near Cache especialmente no lado Java.

quase-cache

Esse recurso, essencialmente, é um cache local. É como seu cache InProc ASP.NET. Ele fica dentro do processo do aplicativo ou pode ser apenas o cache OutProc local, que não é tão rápido quanto o InProc, mas ainda mais rápido do que ir para a camada de cache. Mas, a diferença é que esse cache sabe sobre a camada de cache. Este Client Cache é o cache em cima do cache e é sincronizado. Portanto, você não precisa se preocupar com o maior problema sobre o qual falamos, que é como manter o cache sincronizado com o banco de dados. Bem, agora você tem três cópias dos dados. Um no banco de dados, um na camada de cache, um no Cache do Cliente. Obviamente, o Cache do Cliente é um subconjunto da camada de armazenamento em cache. A camada de cache é um subconjunto do banco de dados. Mas, seja o que for, tem que ser sincronizado. Então, por ter um Client Cache, ele é novamente um InProc, ele mantém as coisas em um formulário de objeto em vez de um formulário serializado. Ele o mantém em sua pilha. Assim, você obtém o mesmo benefício do objeto de cache ASP.NET InProc local, mas com todos os outros benefícios de escalabilidade, pois esse cache do cliente será um pequeno subconjunto. Você pode especificar o tamanho que deve ser. Nunca ultrapassará esse limiar.

Então, você pode ter um gig em cada cache de cliente e você pode ter 32 gigs na camada de cache e o banco de dados provavelmente tem muito mais do que isso. De qualquer forma, mesmo tendo um show porque é uma janela em movimento, certo? Então, o que quer que você esteja fazendo, você mantém. Alguns dos dados permanecerão por muito tempo, alguns dos dados permanecerão por talvez alguns minutos, mas nesse período você fará centenas de chamadas e não precisará ir para a camada de cache e, é claro, não precisará vá para o banco de dados. Portanto, um Cache de Cliente é um recurso realmente poderoso quando você o ativa. Você faz isso para obter mais dados de referência. Então, em caso de NCache, você pode especificar um cache de cliente por meio da alteração de configuração. Não há programação extra, mas é mapeado para um cache específico. Então, é por isso que nossos clientes normalmente têm três caches; cache de objetos, cache de sessão e cache de referência. Para cache de referência eles usam um Cache de Cliente, para os outros dois não.

Fácil de configurar o cache do cliente

Agora, por que eles não fazem um Client Cache com o session cache? Na verdade, porque o desempenho diminui. A razão é porque isso só é melhor se você fizer muito mais leituras e gravações. Porque, o que acontece no caso de uma gravação? Você escreve aqui e depois escreve aqui e depois escreve no banco de dados. Então, você está escrevendo em três lugares. Portanto, não adiciona nenhum valor se você precisar fazer mais gravações. Você atualiza sua cópia e, em seguida, atualiza apenas isso e, em seguida, isso notifica todos os outros Caches de cliente para atualizarem-se. É uma atualização atrasada, não que seja apenas um ou dois milissegundos de atraso, mas ainda é uma atualização atrasada no caso de um Cache de Cliente. Não há replicação entre os Caches de Cliente. O Client Cache apenas se sincroniza com a camada de cache e a camada de cache propaga as atualizações para outros Client Caches. Somente se o outro cache tiver esses dados. Porque, no caso do Client Cache, cada Client Cache possui dados diferentes com base no seu padrão de uso.

Onde usar o Cache do Cliente

Então, vamos voltar atrás, no caso de dados de referência, cada Client Cache tem seu próprio conjunto de dados Então, digamos 1 a 1000, 500 a 1500 e assim por diante. Então, há alguma sobreposição entre cada um, mas eles não são cópias idênticas. O comum é que todos são subconjuntos desse cache. Então, quando eu atualizar o número do item, digamos, 700 neste cache, vai fazer uma atualização no cache e o cache saberá quais outros Caches de Clientes possuem esses itens e eles serão imediatamente atualizados em seus outros caches. Mas, só se todos tiverem. Portanto, não é realmente replicado porque não são cópias idênticas no caso do Client Cache. No caso de sessões, o que eu estava realmente tentando explicar é, no caso de sessão você terá que atualizar o Client Cache e o cache clusterizado, dois lugares sem valor agregado porque para sessões você faz uma leitura e uma gravação. Então, na hora da requisição web, você faz a leitura no final da página você faz a escrita.

Então, a escrita agora tem que ser feita em dois lugares e a leitura vai ser feita no cache do cliente. Portanto, o desempenho realmente cai se você usar o Client Cache com sessões ou com outras operações intensivas de gravação, mas o desempenho melhora tremendamente se você o usar para operações mais intensivas de leitura. Aquilo fez sentido?

Portanto, o maior valor de um cache distribuído, o mais rápido, o mais rápido e o maior é o estado da sessão. Quase todos os aplicativos têm. Acabei de criar um cluster de cache de dois nós e você viu quanto tempo levou, talvez dois minutos, no caso de um NCache. Então, é muito fácil criar um cluster de cache, claro, você quer fazer seus testes e outras coisas. Mas, é muito fácil. Não há esforço de engenharia. Quando não há esforço de engenharia, suas agendas são muito mais fáceis de lidar. Você só precisa fazer um teste de sanidade para passar. Eu recomendo fortemente que, se você for começar a usar um cache distribuído, use-o para o estado das sessões no início como a primeira etapa e, em seguida, pule para o cache de objetos, sobre o qual falaremos em um minuto.

Cache de dados do aplicativo

Então, nós falamos sobre o cache de sessão. Vamos entrar rapidamente no cache de dados do aplicativo. Aqui está o que um típico NCache A API se parece muito com o cache do ASP.NET, se você notar que há uma conexão.

Cache cache = NCache.InitializeCache("myCache");
cache.Dispose();
Buscando dados
Employee employee = (Employee) cache.Get("Employee:1000");
Employee employee = (Employee) cache["Employee:1000"];
bool isPresent = cache.Contains("Employee:1000");
Gravando dados
cache.Add("Employee:1000", employee);
cache.AddAsync("Employee:1000", employee);

cache.Insert("Employee:1000", employee);
cache.InsertAsync("Employee:1000", employee);
cache["Employee:1000"] = employee;

Employee employee = (Employee) cache.Remove("Employee:1000");
cache.RemoveAsync("Employee:1000");

Então, você se conecta com o cache com base no nome e apenas cria um cache com o nome. É por isso que eu lhe dei essa demonstração para que você entendesse o que isso significava. E esse identificador de cache é algo que você preserva apenas como preservaria um identificador de banco de dados. E, então, você usa esse identificador de Cache para fazer um Cache.Get. Cada Get, cada operação, tem uma chave. Uma chave é uma string no caso de NCache e então você formata a chave com base no que está fazendo com ela. Assim, no caso de um objeto individual, uma boa prática é apenas especificar o nome da classe, talvez o nome do atributo e o valor. E então você pode conseguir isso. Então, há um Get e Get.Contains, Add, AddAsync. Assíncrono significa não espere.

Bem, o que acontece é que, por baixo disso, há desserialização acontecendo no cliente. Então, o cliente, vamos fazer um Cache.Add, digamos, você está dando a ele um objeto, é um objeto de funcionário, ele vai serializá-lo com base na serialização .NET padrão ou no personalizado NCache serialização. E, em seguida, crie isso na matriz de bytes e envie a matriz de bytes para o Cache. NCache faz mais do que isso porque você pode precisar indexar certos atributos. Extrai os valores daqueles. Sim, vai. Será. Isso imediatamente. Sim! Cada objeto que você Cache tem que passar por serialização.

Então, assim que você ligar o aplicativo, ele lançará exceções. Se você estiver usando o objeto de cache ASP.NET, não precisará serializar. Portanto, você pode praticamente armazenar tudo em cache e, na maioria das vezes, o que acontece é que seus próprios objetos podem ser mais fáceis de serializar, mas você pode estar usando algum terceiro. Digamos que anteriormente o objeto da tabela de dados não costumava ser serializado, mas agora é. Portanto, se você estiver usando objetos de terceiros que não são serializáveis, você não tem controle. Portanto, você não pode pegá-los se for usar um cache distribuído. No caso de NCache, temos nossa própria serialização personalizada onde você pode identificar esses objetos. NCache em seguida, cria o código de serialização para você em tempo de execução e o compila na memória. Então, isso permite que você use também aqueles objetos que não são serializáveis. Mas, essa serialização acontece imediatamente. Portanto, seu aplicativo não funcionará se não estiver usando a serialização adequada.

Async essencialmente diz que não espere que o cache seja atualizado. Assim, posso continuar. Eu confio que o cache irá adicionar essa coisa. Portanto, eles não desbloqueiam o banco de dados onde as atualizações podem falhar em problemas de integridade de dados. Um cache não tem problemas de integridade de dados. Ele só falha quando você tem falhas. Quando você está sem memória ou algo mais acontece. Portanto, você pode ter certeza de que, seja o que for que estiver adicionando, provavelmente o adicionará ao cache. Portanto, o Async ainda oferece um impulso adicional. Portanto, a API parece muito simples, como você pode ver.

Mantendo o cache atualizado

Então, quando você faz o cache de dados do aplicativo, como você mantém o cache atualizado? Isso é realmente muito importante. Existem diferentes maneiras de armazenar em cache.

manter-cache-fresco

Usando expirações baseadas em tempo

Expirações, quase todos os caches suportam expirações. Há uma expiração absoluta onde você obtém essa especificação para cada item, aqui está quanto tempo eu me sinto confortável para ficar no cache, isso pode ser de 15 segundos a horas, dias e semanas. E isso é para o cache de dados do aplicativo. Há outra expiração chamada expiração deslizante que não é para sincronizar o cache com o banco de dados. É para limpeza. Então, esse ASP.NET, todos os dados transitórios sobre os quais falamos, bem, o que acontece quando você termina com esses dados? Você não deve se preocupar em limpá-lo. Então, você pode especificar uma expiração deslizante e dizer se ninguém usar esses dados por tanto tempo, digamos, no caso de sessões de 20 minutos, se ninguém usar a sessão por esses 20 minutos, remova-o do cache. Então, isso é mais uma limpeza.

Quais são os riscos na expiração? A expiração é, na verdade, você está fazendo um palpite. Você está dizendo, acho que estou bem com cinco minutos, mas não há garantia de que ninguém atualizará esses dados no banco de dados nesse período, especialmente se você tiver outros aplicativos ou outros processos atualizando o banco de dados. Portanto, as expirações são boas apenas em casos de uso limitados.

Usando dependências de banco de dados

Outro recurso muito importante é que você pode ter atualizações inesperadas ou imprevisíveis no banco de dados. Se for esse o caso, o cache deve ter a capacidade de se sincronizar com o banco de dados. Portanto, o cache deve saber sobre seu banco de dados. Ele deve se tornar um cliente do seu banco de dados e monitorar seu banco de dados para quaisquer alterações. Há um recurso no ADO.NET chamado dependência de SQL. Alguém viu isso?

Então, dependência SQL é o que NCache usa para se tornar um cliente do seu servidor SQL ou do seu banco de dados Oracle. Então, no caso do SQL server você pode usar a dependência SQL do SQL server ADO.NET Feature que NCache usa para obter eventos do banco de dados. O Cache, NCache torna-se um cliente do seu banco de dados. Ele recebe eventos e, em seguida, com base nisso, faz suas próprias coisas. Em alguns casos, você não tem eventos. Então, digamos, se você tivesse db2 ou MySQL, eles não teriam eventos. Então, o cache deve ser capaz de fazer polling. NCache também suporta o polling baseado. Então, você faz a mesma coisa, você armazena este item no cache e você disse que isso mapeia para esta linha nesta tabela e então NCache fará o polling e, se esses dados forem alterados, ele os removerá novamente do cache ou recarregará uma nova cópia. Mas, esse recurso, dá muito conforto.

Novamente, a mesma coisa que eu estava falando é que você quer ter certeza de que o Cache está sempre sincronizado com o banco de dados. A expiração é boa o suficiente para apenas um pequeno subconjunto dos casos de uso.

Portanto, você terá uma perda de cache se não fizer uma recarga automática. Então, quando você quando a dependência do SQL é acionada, ela remove, NCache remove o item do cache. Então, se o seu aplicativo quiser, será uma falha de cache e você será forçado a ir e obter uma nova cópia do banco de dados. Se você não quer uma perda de cache que está em muitos dos aplicativos de comércio eletrônico porque eles estão lendo dados com tanta frequência que não querem que nada aumente a carga no banco de dados, então, você usaria a dependência SQL com esse recurso chamado leitura.

Na verdade, preciso mostrar um código para você, caso contrário, começa a ficar muito chato. Então, deixe-me mostrar-lhe rapidamente. Então, eu tenho apenas um aplicativo de console muito simples. No caso de NCache, tudo o que você precisa fazer é adicionar alguns assemblies aqui. Então, há NCache.Tempo de execução e NCache.Rede. Então você especifica alguns namespaces esses dois e então você se conecta ao Cache e você tem seu handle de Cache e, então você cria um objeto e então você faz Cache.Add. E, você especifica a chave. Esta não é uma boa chave. Eu pretendia alterá-lo, mas sua chave deve ter o valor real nela. Então, você faz um Cache.Add e especifica o objeto.

Nesse caso, também estou usando uma expiração absoluta de um minuto. Então, você especifica a expiração absoluta e pronto. Isso é tudo que você faz para adicionar isso ao Cache. Da próxima vez que você precisar, basta fazer um Cache.Get, especificar a mesma chave e obterá o objeto de volta. Muito, muito simples para uma expiração absoluta. Você pode fazer a mesma coisa para a expiração deslizante. Embora, em vez de especificar um valor absoluto, você precise especificar um intervalo como 10 minutos ou 20 minutos. Dependência SQL é o que eu queria mostrar a você. O que isso parece. Lá! Portanto, o mesmo tipo de aplicativo. Você só precisa adicionar esses dois aqui e especificar os namespaces e, em seguida, quando você adicionar as coisas ao Cache, é quando você especifica a dependência do SQL.

Deixe-me apenas ir para a definição disso. Então, vou adicionar isso ao Cache aqui. Então, eu tenho minha chave que é o que eu mostrei a você da última vez. Agora, em vez de adicionar o objeto, vou adicionar um item de Cache. Isso é um NCache estrutura. Então, ele armazena o objeto real e também uma dependência SQL. Então, NCache tem um objeto de dependência de cache. Então, eu faço uma nova dependência do SQL Cache. Isso é um NCache classe que mapeia internamente a dependência SQL dos servidores SQLs. Então, você passa uma string de conexão e a string de conexão é sua string de conexão do servidor SQL e você passa uma instrução SQL. Então, aqui no meu caso, eu especifiquei select this onde o ID do produto é qualquer que seja o meu valor. Então, estou apenas mapeando-o para uma linha na tabela de produtos. E, especificando tanto isso, acabei de dizer NCache para se tornar um cliente do servidor SQL. E remova este item se isso mudar, se essa linha mudar no banco de dados.

Então, depende de qual é a instrução SQL. Portanto, se o método de sequência contém apenas uma linha, ele mapeia para fazer apenas uma linha e é isso que vai ser. Normalmente você não pode fazer junções nisso e essa é a limitação do recurso de dependência SQL no ADO.NET, mas, para uma única tabela, você pode fazer isso facilmente. Então, é assim que você faria o…

Então, o SQL Server tem essa coisa chamada SQL broker. Então, na verdade, ele cria um conjunto de dados ou uma estrutura de dados no servidor SQL para monitorar esses conjuntos de dados. Assim, todas as dependências SQL que você cria, o SQL Server cria estruturas de dados para ir e monitorar os conjuntos de dados. E, com base nisso, ele envia uma notificação SQL.

Portanto, você precisa configurar isso no servidor SQL porque também é uma questão de segurança, então seu banco de dados precisa se envolver na configuração do servidor SQL, mas é bastante simples. Quero dizer, não há programação ou qualquer coisa necessária no servidor e apenas uma configuração. Todo o material é cuidado pelo lado do cliente.

Leitura e gravação

Ok! Então, fizemos a dependência SQL. Eu queria te mostrar então se você não quiser remover este item do cache, você pode fazer um recarregamento através de uma leitura. Portanto, a leitura é outro recurso muito poderoso.

leitura-através-gravação-através

Read-through é um código do lado do servidor. Na verdade, a leitura é o seu código que é executado no cluster de cache. Então, você realmente registra seu código e ele é executado no cluster de cache. se chama bi NCache. E, o valor de uma leitura... deixe-me mostrar primeiro como é a leitura e mostrarei qual é o valor, quero dizer, por que você quer fazer a leitura. Então, aqui está a aparência de uma leitura típica. É uma interface IReadThrough. Você faz um InIt para poder se conectar às suas fontes de dados. Você faz um descarte, é claro, e então há uma carga da fonte. Ele passa sua chave e espera e um cache de itens de volta. Portanto, o item de cache contém seu objeto e várias outras coisas que você pode especificar expirações e outras coisas dentro dele. Interface muito simples.

Isso é chamado por NCache Então, você implementa essa interface e registra seu assembly. No caso de NCache, você registra seu assembly com o Cache e agora quando você faz um Cache.Get e esse item não existe no cache, o cache na verdade, NCache chamará sua leitura para obtê-lo de suas fontes de dados. Sua fonte de dados pode ser um banco de dados, pode ser um mainframe, qualquer fonte de dados. Assim, ao fazer uma leitura, você pode garantir que um cache sempre tenha os dados e o que o aplicativo vê. Então, esse é um benefício.

O segundo benefício é o recarregamento que… Assim, você pode realmente combinar a leitura. Assim, você pode na expiração e na sincronização do banco de dados, quando o item seria removido do cache e você não deseja removê-lo porque você vai recarregá-lo novamente de qualquer maneira. Então, por que não fazer o cache recarregá-lo dessa maneira, porque se você, basta pensar nisso, você tem milhões de itens no cache e todos eles estão expirando o tempo todo, certo? Porque é assim que você configurou. E, você tem um e-commerce e um aplicativo de tráfego muito alto e toda vez que algo expira, você tem muitos pedidos simultâneos para isso. Todos eles irão para o banco de dados. Então, de repente, o tráfego do banco de dados aumentou sem motivo, mesmo que você simplesmente não precise dele no cache de qualquer maneira.

Portanto, como isso continua acontecendo o tempo todo, você verá muitos picos no tráfego do banco de dados, apesar de ter cache. Então, é aí que, ter um recarregamento significa que ele nunca é removido do cache. Apenas é atualizado. Assim, seus aplicativos nunca irão para o banco de dados. Eles continuarão recebendo a cópia antiga até o ponto em que você a atualizar. Então, de repente, você removeu ou cuidou desse problema em que, embora tivesse o cache, estava vendo muitos picos no tráfego do banco de dados devido às expirações ou à sincronização do banco de dados. Então, fazer o cache recarregar isso através da leitura, realmente o torna muito poderoso.

O outro benefício da leitura, é claro, é que você está centralizando, simplificando a camada do aplicativo porque cada vez mais o acesso ao banco de dados é feito pelo cache. Portanto, se você tiver vários aplicativos acessando os mesmos dados, poderá realmente centralizar o acesso aos dados na camada de armazenamento em cache. Claro, você não pode fazer isso para todos os dados, mas para muitos dos dados que você pode.

O write-through funciona da mesma forma que o read-through. Deixe-me apenas ir para a escrita. Funciona da mesma forma. Ele tem um provedor de gravação, novamente InIt, descartado e agora, em vez de carregar, é uma gravação na fonte de dados e tem outro tipo de gravação em massa. Write-through, um benefício é o mesmo que ler, que é você centralizar tudo. O segundo benefício é que você pode fazer um write-behind que é atualizar o cache que é, como eu disse, dez vezes mais rápido que o banco de dados e então você pede ao cache para atualizar o banco de dados. E, o write-behind é essencialmente o mesmo que o write-through, mas feito de maneira assíncrona. É uma fila que é criada e processada. Essa fila também é replicada em caso de NCache. Portanto, nenhuma das atualizações será perdida se algum servidor cair. Mas, o write-behind realmente acelera o aplicativo porque, quero dizer, você já o tornou mais rápido armazenando em cache para fazer todas as leituras, certo? Portanto, cerca de 70 a 80 por cento das leituras são agora ou as transações estão indo para o cache de qualquer maneira. Por que não também acelerar as gravações? Se você puder fazer isso de uma maneira write-behind, se puder fazer uma gravação assíncrona. Se os dados são muito sensíveis onde você não pode pagar, você faz uma gravação e obtém apenas o primeiro benefício, que é a centralização do código. O segundo benefício do desempenho mais rápido vem apenas se você puder fazer assíncrono.

Conclusão

A ideia é que quando você começar a fazer o cache, não pense em um cache que é apenas um valor de chave simples aqui, quero dizer, todo o meu propósito foi primeiro convencê-lo de que você realmente precisa de um cache distribuído como parte do sua infraestrutura e a arquitetura do aplicativo. Se você deseja que os aplicativos sejam dimensionados, você deve incorporar isso independentemente de qual produto de armazenamento em cache você usa, quero dizer, você deve tê-lo. Atualmente para o pessoal do .NET, as opções no mercado são NCache que é um código aberto e também comercial. Há Redis que a Microsoft disponibilizou pelo menos no Azure. No Azure é um serviço de cache gerenciado, fora dele você precisa instalá-lo e ele é instalado principalmente no Linux, a menos que você use a versão sem suporte de código aberto. No lado do Java, há muito mais opções de armazenamento em cache. Então, esse foi o primeiro de tudo.

Segundo objetivo que você deve entender, não é um valor-chave simples. Você quer ter certeza de que pode armazenar em cache todos os tipos de dados e lidar com todos os tipos de situações em que você obtém o benefício real. E nem cheguei à outra parte porque, na verdade, estou ficando sem tempo, que era, por exemplo, como você faz o compartilhamento de dados em tempo de execução e quais são algumas das coisas arquitetônicas que você deseja garantir que o cache é sempre dinâmico para que você possa configurar as coisas. Faz parte do seu data center, faz parte do seu ambiente de produção. Portanto, qualquer cache que não permita que você faça alterações em tempo de execução não é um bom cache para escolher. Então você vai ficar preso com um monte de tempos de inatividade, nós temos clientes que agendam tempos de inatividade uma vez por ano, você sabe. Então, alguns de nossos clientes nem têm isso porque têm uma disponibilidade tão alta.

alta disponibilidade

Eles querem até atualizar o próprio cache para uma nova versão sem tempo de inatividade. Então, quero dizer, depende de quais são as suas necessidades de negócios. Mas, todas essas coisas precisam ser levadas em consideração, muitas pessoas têm vários data centers agora. Pelo menos para fins de DR e também para balanceamento de carga geográfico, se você tiver isso, espera que seu banco de dados seja replicado, certo?

wan-replicação

Então, por que o cache não deveria dar suporte a vários data centers? Porque, quanto menos um cache puder fazer, mais você terá que fazer. Essa é a linha de fundo. Como as necessidades do seu aplicativo não serão alteradas, o cache precisa acomodar. Então, tenha tudo isso em mente.

Então, há uma comparação entre NCache e Redis.

redis-vs-ncache

Ambos são de código aberto. NCache também tem Enterprise Edition. Então, basicamente, se o seu .NET, NCache encaixa muito bem. No NCache, N significa .NET, linha de fundo, quero dizer, é assim que estamos comprometidos com o .NET.

O que fazer a seguir?

 

Inscreva-se no boletim informativo mensal por e-mail para obter as atualizações mais recentes.

© Copyright Alachisoft 2002 - . Todos os direitos reservados. NCache é uma marca registrada da Diyatech Corp.