Cache em C++: Redis e outras ferramentas para acelerar aplicações
Cache é um dos mecanismos-chave de otimização de desempenho de aplicações em C++. Em sistemas modernos, onde a velocidade de acesso aos dados é crítica (servidores web, jogos, backends de alta carga), um cache bem configurado pode reduzir o tempo de resposta dezenas de vezes. Neste artigo, vamos analisar como organizar o cache em C++ usando Redis e soluções alternativas, incluindo estruturas de dados embutidas.
Por que o cache é necessário em C++?
O principal objetivo do cache é armazenar dados frequentemente solicitados em um armazenamento rápido (geralmente em RAM) para evitar operações caras repetidas: consultas ao banco de dados, cálculos ou chamadas de rede. Para C++, isso é especialmente relevante, pois a linguagem é usada em sistemas de tempo real e serviços de alta carga.
Redis — cache distribuído para C++
Redis é um armazenamento de dados in-memory frequentemente usado como cache. Para trabalhar com Redis a partir de C++, existem várias bibliotecas maduras:
- hiredis — biblioteca C minimalista, cliente oficial do Redis. Leve, mas requer gerenciamento manual de memória e tipagem estrita.
- redis-plus-plus — wrapper moderno C++17 sobre hiredis. Suporta pools de conexão, transações, Redis Cluster e operações assíncronas.
- cpp_redis — outra biblioteca C++11 com sintaxe semelhante ao hiredis, mas com API mais conveniente.
Exemplo de conexão e uso básico do redis-plus-plus:
#include <sw/redis++/redis++.h>
using namespace sw::redis;
int main() { // Conexão ao Redis (servidor local, porta 6379) auto redis = Redis("tcp://127.0.0.1:6379");
// Escrita no cache com TTL (tempo de vida de 60 segundos) redis.setex("user:123:profile", 60, "{\\"name\\":\\"Alice\\",\\"age\\":30}");
// Leitura do cache auto val = redis.get("user:123:profile"); if (val) { std::cout << "Cache encontrado: " << *val << std::endl; } else { std::cout << "Cache vazio, é necessário carregar dados do BD" << std::endl; }
return 0;}Vantagens do Redis: distribuído, suporte a estruturas complexas (listas, hashes, conjuntos), TTL, pub/sub. Desvantagens: necessidade de um servidor separado, latência de rede (embora mínima).
Caches embutidos em C++: cache LRU e nível de dados
Se você não precisa de um sistema distribuído, pode implementar o cache diretamente na aplicação. O algoritmo mais popular é o LRU (Least Recently Used). Ele remove os dados que não foram usados por mais tempo.
Exemplo de implementação de um cache LRU simples em C++17 usando std::unordered_map e std::list:
#include <unordered_map>#include <list>#include <stdexcept>
template<typename Key, typename Value>class LRUCache {public: LRUCache(size_t capacity) : capacity_(capacity) {}
Value get(const Key& key) { auto it = cache_.find(key); if (it == cache_.end()) { throw std::runtime_error("Key not found"); } // Move o elemento para o início da lista (mais recentemente usado) order_.splice(order_.begin(), order_, it->second.second); return it->second.first; }
void put(const Key& key, const Value& value) { auto it = cache_.find(key); if (it != cache_.end()) { // Atualiza o valor e move para o início it->second.first = value; order_.splice(order_.begin(), order_, it->second.second); return; } // Se o cache estiver cheio, remove o último elemento (LRU) if (cache_.size() == capacity_) { auto last = order_.back(); order_.p Também na biblioteca
Configuração de aplicações Java: bibliotecas e ferramentas para gerenciamento de configurações
Actix-web para Rust: guia completo com exemplos
Geração de QR Codes em PHP: biblioteca phpqrcode e guia completo
Gerador de QR Codes em Rust: biblioteca qr_code