Dominando o Redis no .NET Core com CSRedisCore

A comunidade .NET Core está em constante expansão, trazendo consigo ferramentas cada vez mais eficientes para interagir com tecnologias populares como o Redis. Diversas bibliotecas para .NET Core já foram apresentadas, cada uma com suas particularidades. ServiceStack.Redis, por exemplo, possui limitações em sua versão gratuita, enquanto StackExchange.Redis, apesar de gratuito, historicamente apresentou problemas de timeout em ambientes .NET Core, embora versões mais recentes possam ter mitigado essa questão. O csredis original, embora com código limpo e fácil de entender, não suporta .NET Core.

Felizmente, desenvolvedores brasileiros têm contribuído significativamente para o ecossistema .NET Core com bibliotecas robustas para Redis. Duas opções notáveis são:

  1. NewLife.Redis: Desenvolvido pela equipe NewLife, esta biblioteca é utilizada em larga escala em sistemas de processamento de dados em tempo real, gerenciando centenas de instâncias Redis e processando bilhões de chamadas diariamente.
  2. CSRedisCore: Criado pelo desenvolvedor "nicye", esta biblioteca é a escolha principal em muitos projetos, incluindo o deste artigo. O autor realizou testes de performance comparativos entre diversos drivers Redis para .NET Core, cujos resultados podem ser encontrados em discussões online. É importante não confundir esta versão com o antigo componente CSRedis, que não é compatível com .NET Core.

Este artigo foca no uso do CSRedisCore, uma ferramenta poderosa e de fácil utilização para gerenciar suas instâncias Redis no .NET Core.

Uso Básico do CSRedisCore

A utilização do CSRedisCore é intuitiva. Após a instalação via NuGet, você instnacia um objeto CSRedisClient, que pode ser configurado para diversos cenários, como conexão única, cluster oficial ou um modelo de particionamento customizado. A inicialização do RedisHelper com este cliente disponibiliza métodos cujos nomes espelham os comandos do redis-cli, facilitando a transição. Funcionalidades como Pipeline e operações em lote (MGet, MSet) também são suportadas para otimização.

Instalação e Configuração

Para começar, instale o pacote via NuGet:

Install-Package CSRedisCore

O CSRedisClient pode ser configurado de diferentes maneiras:

  • Modo Padrão: Conexão direta a uma instância Redis. ``` var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379,password=senha123,defaultDatabase=13,poolsize=50,ssl=false,writeBuffer=10240,prefix=meuApp:");
  • Modo Cluster Oficial: Para ambientes clusterizados com redis-trib. O cliente se adapta dinamicamente aos nós do cluster. ``` // Exemplo de configuração inicial, o cliente descobre os outros nós automaticamente. var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379,password=senha123,defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240");
    
    **Atenção:** Este modo tem limitações com comandos multi-chave, pipelines e scripts. É desaconselhável usar o parâmetro `prefix` em conjunto com o modo de particionamento para evitar conflitos de mapeamento de slots.
    
  • Modo de Particionamento (Customizado): Uma abordagem implementada pelo autor para distribuir dados entre múltiplos servidores Redis, ideal para grandes volumes de cache. ``` var csredis = new CSRedis.CSRedisClient(null, "192.168.1.10:6371,password=senha123,defaultDatabase=11,poolsize=10", "192.168.1.11:6372,password=senha123,defaultDatabase=12,poolsize=11", "192.168.1.12:6373,password=senha123,defaultDatabase=13,poolsize=12"); // A distribuição das chaves é feita por meio de hash e módulo da quantidade de nós.
    
    

Exemplo Prático (Modo Padrão)

A configuração a seguir demonstra o uso básico com o modo padrão e a inicialização do RedisHelper.


   using CSRedis;
   using System;
   using System.Threading;

   public class Program
   {
       static void Main(string[] args)
       {
           // Configuração do cliente Redis
           var redisClient = new CSRedis.CSRedisClient("127.0.0.1:6379,password=senha123,defaultDatabase=1,poolsize=50,writeBuffer=10240");

           // Inicializa o RedisHelper
           RedisHelper.Initialization(redisClient);

           // Exemplo de testes
           ExecuteRedisOperations();

           Console.WriteLine("Pressione qualquer tecla para sair...");
           Console.ReadKey();
       }

       static void ExecuteRedisOperations()
       {
           // Operações Simples
           RedisHelper.Set("usuarioNome", "Carlos Silva"); // Define um valor com expiração padrão
           Console.WriteLine($"Nome do usuário: {RedisHelper.Get<string>("usuarioNome")}");

           var now = DateTime.Now;
           RedisHelper.Set("timestampAtual", now, 2); // Define com expiração de 2 segundos
           Console.WriteLine($"Timestamp inicial: {RedisHelper.Get<DateTime>("timestampAtual")}");
           Thread.Sleep(2100); // Aguarda expiração
           Console.WriteLine($"Timestamp após expirar: {RedisHelper.Get<DateTime>("timestampAtual")}");

           // Operações com Listas
           RedisHelper.RPush("filaItens", "Item A");
           RedisHelper.RPush("filaItens", "Item B");
           RedisHelper.LInsertBefore("filaItens", "Item B", "Item Intermediário");
           Console.WriteLine($"Tamanho da lista 'filaItens': {RedisHelper.LLen("filaItens")}");
           Console.WriteLine($"Segundo elemento da lista 'filaItens': {RedisHelper.LIndex("filaItens", 1)}");

           // Operações com Hashs
           RedisHelper.HSet("dadosPessoais", "nome", "Maria Souza");
           RedisHelper.HSet("dadosPessoais", "idade", "30");
           RedisHelper.HSet("dadosPessoais", "cidade", "Rio de Janeiro");
           Console.WriteLine($"Idade em 'dadosPessoais': {RedisHelper.HGet<int>("dadosPessoais", "idade")}");

           // Operações com Sets
           RedisHelper.SAdd("conjuntoAlunos", "Ana", "Bruno");
           RedisHelper.SAdd("conjuntoAlunos", "Carlos");
           Console.WriteLine($"Tamanho do conjunto 'conjuntoAlunos': {RedisHelper.SCard("conjuntoAlunos")}");
           Console.WriteLine($"'Ana' está no conjunto 'conjuntoAlunos'? {RedisHelper.SIsMember("conjuntoAlunos", "Ana")}");
       }
   }
   

Note que todos os métodos de acesso ao Redis são delegados ao RedisHelper, e a nomenclatura dos métodos é diretamente inspirada nos comandos do redis-cli. Tanto operações síncronas quanto assíncronas estão disponíveis.

Uso Avançado

Publicação e Subscrição (Pub/Sub)

O CSRedisCore facilita a implementação de padrões de mensagens com seus recursos de pub/sub.


   // Assinatura de canais específicos
   RedisHelper.Subscribe(
     ("canalNoticias", msg => Console.WriteLine($"Canal Noticias: {msg.Body}")),
     ("canalAlertas", msg => Console.WriteLine($"Canal Alertas: {msg.Body}")));

   // Assinatura de canais com padrões (wildcards)
   RedisHelper.PSubscribe(new[] { "log.*", "*.erro" }, msg => {
     Console.WriteLine($"Wildcard Match -> Channel: {msg.Channel}, Pattern: {msg.Pattern}, Message: {msg.Body}");
   });

   // Publicação de mensagens
   RedisHelper.Publish("canalNoticias", "Nova atualização disponível!");
   RedisHelper.Publish("log.info", "Processo concluído com sucesso.");
   

Cache Shell

Simplifica a lógica de cache, verificando o Redis antes de consultar a fonte de dados original e armazenando o resultado.


   // Exemplo com chave simples e expiração de 10 segundos
   var itemCache = RedisHelper.CacheShell("chaveUnica", 10, () => {
       // Lógica para buscar dados da fonte original (ex: banco de dados)
       return ObterDadosDaFonteOriginal(1);
   });

   // Exemplo com chave composta e tipo Hash
   var itemHashCache = RedisHelper.CacheShell("chaveHash", "subChave", 10, () => {
       return ObterDadosDaFonteOriginal(2);
   });

   // Exemplo para múltiplas chaves em Hash
   var variosItensHash = RedisHelper.CacheShell("conjuntoChaves", new[] { "id1", "id2" }, 10, chavesNaoEncontradas => {
     // Retorna um dicionário de chave-valor para as chaves que não estavam no cache
     return new Dictionary<string, object> {
       { "id1", ObterDadosDaFonteOriginal(3) },
       { "id2", ObterDadosDaFonteOriginal(4) }
     };
   });
   

Pipeline e Operações em Lote

Utilize Pipeline para agrupar múltiplos comandos e executá-los de forma mais eficiente.


   // Execução de múltiplos comandos em um único pipeline
   var pipelineResult1 = RedisHelper.StartPipe()
                                   .Set("chaveA", "valorA")
                                   .Get("chaveA")
                                   .Expire("chaveA", 60)
                                   .EndPipe();
   // Acessa o resultado do comando Get
   var valorA = pipelineResult1[1];

   // Outra forma de usar pipeline com Action
   var pipelineResult2 = RedisHelper.StartPipe(pipe => {
       pipe.Set("chaveB", "valorB");
       pipe.Increment("contador", 1);
   });

   // Comparação de performance com MGet
   var multiGetResult = RedisHelper.MGet("chave1", "chave2", "chave3");
   // O pipeline pode oferecer performance semelhante ou superior em alguns casos.
   

Testes de Performance

Para uma análise detalhada da performance do CSRedisCore em comparação com outras bibliotecas .NET Core para Redis, consulte os benchmarks realizados pelo autor e pela comunidade.

A comunidade de desenvolvedores .NET Core está vibrante, com ferramentas excelentes surgindo constantemente. O CSRedisCore é um exemplo notável de como podemos interagir de forma eficiente e simplificada com o Redis em nossos projetos .NET Core.

Tags: dotnet core Redis csrediscore nosql cache

Publicado em 7-7 01:14