Skip to content

Projeto de exemplo demonstrando a implementação de cache distribuído com Redis em aplicações .NET. Utiliza uma API de pagamentos como caso de uso prático para ilustrar padrões de cache, persistência em memória e otimização de performance.

License

Notifications You must be signed in to change notification settings

emensonlima01/redis-cache-dotnet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Redis Cache com .NET

Descrição

Projeto de exemplo demonstrando a implementação de cache distribuído com Redis em aplicações .NET. Utiliza uma API de pagamentos como caso de uso prático para ilustrar padrões de cache, persistência em memória e otimização de performance.

O que este projeto demonstra

  • Integração do Redis com ASP.NET Core 8.0
  • Implementação do padrão Cache-Aside
  • Abstração de serviço de cache para facilitar manutenção
  • Serialização e deserialização de objetos complexos
  • Configuração de TTL (Time To Live) para expiração de dados
  • Uso de chaves estruturadas para organização de dados
  • Deploy containerizado com Docker Compose

Como o Redis é Utilizado

Padrão Cache-Aside

O projeto implementa o padrão Cache-Aside onde:

  1. Leitura: Primeiro tenta buscar do cache, se não encontrar, retorna null
  2. Escrita: Sempre salva no cache com tempo de expiração configurável
  3. Atualização: Sobrescreve o valor existente no cache

Estrutura de Chaves

As chaves seguem o padrão {prefixo}:{identificador}:

payment:3fa85f64-5717-4562-b3fc-2c963f66afa6

Configuração do Redis

Política de Memória: allkeys-lru - Remove as chaves menos recentemente usadas quando atinge o limite de memória

Limite de Memória: 128MB

Persistência: Desabilitada para máxima performance (dados apenas em memória)

Tempo de Expiração: 1 hora (configurável por operação)

Abstração do Cache

O projeto utiliza uma interface ICacheService que abstrai as operações do Redis:

public interface ICacheService
{
    Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default);
    Task SetAsync<T>(string key, T value, TimeSpan? expiration = null, CancellationToken cancellationToken = default);
    Task<bool> RemoveAsync(string key, CancellationToken cancellationToken = default);
    Task<bool> ExistsAsync(string key, CancellationToken cancellationToken = default);
    Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiration = null, CancellationToken cancellationToken = default);
}

Essa abstração permite trocar a implementação de cache sem impactar o restante da aplicação.

Tecnologias

  • Redis 7 Alpine - Banco de dados em memória
  • StackExchange.Redis - Cliente Redis para .NET
  • ASP.NET Core 8.0 - Framework para API de exemplo
  • System.Text.Json - Serialização de objetos
  • Docker Compose - Orquestração de containers
  • Clean Architecture - Separação de responsabilidades

Configuração

Pré-requisitos

  • Docker e Docker Compose instalados

Executar o Projeto

docker-compose up -d

Isso irá iniciar dois containers:

  • Redis na porta 6379
  • API de exemplo na porta 5192

Variáveis de Ambiente

Variável Descrição Valor
Redis__ConnectionString String de conexão do Redis redis:6379

Conectar ao Redis

O Redis estará disponível em localhost:6379. Você pode conectar usando:

# Via Redis CLI
docker exec -it payment-redis redis-cli

# Comandos úteis
redis-cli ping
redis-cli keys "payment:*"
redis-cli get "payment:{guid}"
redis-cli ttl "payment:{guid}"

Testar a API de Exemplo

Acesse http://localhost:5192/swagger para explorar os endpoints de exemplo e ver o Redis em ação.

Exemplo de fluxo:

  1. POST /api/payment - Cria um pagamento e salva no Redis
  2. GET /api/payment/{id} - Busca do Redis (cache hit)
  3. Aguarde 1 hora - Dados expiram automaticamente
  4. GET /api/payment/{id} - Retorna 404 (cache miss, dados expiraram)

Implementação do Redis

Conexão com Redis

// Infrastructure/Extensions/CacheDependencyInjection.cs
services.AddSingleton<IConnectionMultiplexer>(sp =>
{
    var configuration = ConfigurationOptions.Parse(connectionString);
    configuration.AbortOnConnectFail = false;
    return ConnectionMultiplexer.Connect(configuration);
});

services.AddSingleton<ICacheService, RedisCacheService>();

Serviço de Cache

// Infrastructure/Services/RedisCacheService.cs
public class RedisCacheService : ICacheService
{
    private readonly IDatabase _database;

    public async Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default)
    {
        var value = await _database.StringGetAsync(key);
        if (!value.HasValue) return default;

        return JsonUtil.Deserialize<T>(value!);
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan? expiration = null, CancellationToken cancellationToken = default)
    {
        var json = JsonUtil.Serialize(value);
        await _database.StringSetAsync(key, json, expiration);
    }
}

Uso no Repository

// Infrastructure/Repositories/PaymentRepository.cs
public class PaymentRepository : IPaymentRepository
{
    private const string KeyPrefix = "payment";
    private static readonly TimeSpan DefaultExpiration = TimeSpan.FromHours(1);

    public async Task<Guid> CreateAsync(Payment payment, CancellationToken cancellationToken = default)
    {
        var key = $"{KeyPrefix}:{payment.Identifier}";
        await _cacheService.SetAsync(key, payment, DefaultExpiration, cancellationToken);
        return payment.Identifier;
    }

    public async Task<Payment?> GetByIdentifierAsync(Guid identifier, CancellationToken cancellationToken = default)
    {
        var key = $"{KeyPrefix}:{identifier}";
        return await _cacheService.GetAsync<Payment>(key, cancellationToken);
    }
}

Recursos do Redis

Configuração do Container

redis:
  image: redis:7-alpine
  command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru --save "" --appendonly no
  deploy:
    resources:
      limits:
        cpus: '0.25'
        memory: 128M

Parâmetros importantes:

  • --maxmemory 128mb - Limita uso de memória
  • --maxmemory-policy allkeys-lru - Remove chaves antigas quando memória está cheia
  • --save "" - Desabilita persistência em disco
  • --appendonly no - Desabilita log de operações

Monitoramento do Redis

Verificar Chaves Armazenadas

# Listar todas as chaves de pagamento
redis-cli keys "payment:*"

# Ver quantidade de chaves
redis-cli dbsize

# Verificar tempo de vida restante de uma chave (em segundos)
redis-cli ttl "payment:3fa85f64-5717-4562-b3fc-2c963f66afa6"

Estatísticas do Redis

# Informações gerais do servidor
redis-cli info

# Uso de memória
redis-cli info memory

# Estatísticas de operações
redis-cli info stats

Limpar Cache

# Remover uma chave específica
redis-cli del "payment:3fa85f64-5717-4562-b3fc-2c963f66afa6"

# Remover todas as chaves de pagamento
redis-cli keys "payment:*" | xargs redis-cli del

# Limpar todo o banco de dados (cuidado!)
redis-cli flushdb

Arquitetura do Projeto

O projeto segue Clean Architecture com separação clara de responsabilidades:

Solution/
├── Domain/              # Regras de negócio e contratos
│   ├── Entities/       # Entidades do domínio
│   ├── Repositories/   # Interface do repositório
│   └── Services/       # Interface ICacheService
├── Application/        # Casos de uso
│   ├── UseCases/      # Lógica de aplicação
│   └── DTOs/          # Objetos de transferência
├── Infrastructure/     # Implementações técnicas
│   ├── Services/      # RedisCacheService (implementação)
│   ├── Repositories/  # PaymentRepository (usa Redis)
│   └── Extensions/    # Configuração de DI
├── WebApi/            # API REST (exemplo)
│   └── Controllers/   # Endpoints HTTP
└── Shared/            # Utilitários compartilhados
    └── Utils/         # JsonUtil para serialização

Benefícios desta arquitetura:

  • Fácil substituição do Redis por outro cache (Memcached, etc.)
  • Testabilidade através de interfaces
  • Separação entre regras de negócio e infraestrutura

Referências

Redis

.NET

Arquitetura

About

Projeto de exemplo demonstrando a implementação de cache distribuído com Redis em aplicações .NET. Utiliza uma API de pagamentos como caso de uso prático para ilustrar padrões de cache, persistência em memória e otimização de performance.

Topics

Resources

License

Stars

Watchers

Forks