O caching é uma técnica comummente utilizada em tecnologias de informação para melhorar o desempenho das aplicações e reduzir a carga nos sistemas backend. Ao armazenar dados acedidos frequentemente numa cache, as aplicações podem evitar a sobrecarga de aceder repetidamente a sistemas de armazenamento mais lentos, como bases de dados ou sistemas de ficheiros.
Neste artigo, iremos discutir os principais padrões de cache que são vulgarmente utilizados em TI, bem como as vantagens e desvantagens de cada um. Exploraremos também alguns dos principais desafios do cache e como superá-los.
Padrão Cache-Aside
O padrão Cache-Aside é um dos padrões de cache mais comuns. Neste padrão, a aplicação acede diretamente ao cache em vez de passar por uma camada de middleware. Quando a aplicação necessita de dados, verifica primeiro o cache. Se os dados não estiverem no cache, a aplicação obtém-nos do sistema backend e armazena-os no cache para uso futuro.
O padrão Cache-Aside é simples e fácil de implementar, proporcionando um bom equilíbrio entre taxas de acerto na cache e consistência dos dados. No entanto, requer também uma gestão cuidadosa do tamanho da cache e das políticas de remoção para evitar sobrecarregar a cache ou armazenar dados desatualizados.

Padrão de Leitura Única
O padrão Read-Through é outro padrão de cache comummente utilizado. Neste padrão, a aplicação acede à cache indiretamente através de uma camada middleware. Quando a aplicação necessita de dados, envia um pedido ao middleware, que primeiro verifica a cache. Se os dados não estiverem na cache, o middleware vai buscá-los ao sistema de backend e armazena-os na cache antes de os devolver à aplicação.
O padrão Read-Through é útil quando a aplicação necessita aceder a dados que são dispendiosos de ir buscar ao sistema de backend, e quando a camada de middleware pode adicionar funcionalidade adicional, como transformação de dados ou lógica de caching. No entanto, também pode adicionar latência e complexidade adicionais à arquitetura da aplicação.

Padrão Write-Through
O padrão Write-Through é um padrão de cache utilizado para manter o cache sincronizado com o sistema de backend. Neste padrão, a aplicação escreve dados para a camada de middleware de cache, que depois os escreve no sistema de backend de forma síncrona. Isto garante que os dados no cache estão sempre consistentes com os dados no sistema de backend.
O padrão Write-Through é útil quando a consistência dos dados é crítica e quando as operações de escrita são infrequentes. Contudo, também pode adicionar latência adicional às operações de escrita e aumentar a carga no sistema de backend.

Padrão Write-Behind
O padrão Write-Behind é uma extensão do padrão Cache-Aside que oferece uma estratégia para lidar com operações de escrita. Neste padrão, quando a aplicação escreve dados na cache, a cache retorna imediatamente uma resposta de sucesso à aplicação sem esperar que os dados sejam escritos no sistema de backend. A cache escreve então os dados de forma assíncrona para o sistema de backend.
O padrão Write-Behind pode ajudar a reduzir a latência e melhorar o throughput das operações de escrita. No entanto, introduz também o risco de inconsistência de dados se os dados forem atualizados na cache antes de serem escritos no sistema de backend.

Padrão de Escrita Circular
O padrão Write-Around é um padrão de cache que contorna a cache para operações de escrita. Neste padrão, quando a aplicação escreve dados, estes são escritos diretamente no sistema de backend, contornando completamente a cache.
O padrão Write-Around é útil quando a aplicação está a executar um grande número de operações de escrita que não beneficiam de serem cacheadas. No entanto, pode reduzir a taxa global de acertos do cache e aumentar a carga no sistema de backend.
Padrão Refresh-Ahead
O padrão Refresh-Ahead é um padrão de cache que atualiza proativamente os dados antes de serem solicitados pela aplicação. Neste padrão, a cache atualiza periodicamente os dados em segundo plano para garantir que estejam atualizados e prontos quando a aplicação precisar deles.
O padrão Refresh-Ahead é útil quando a aplicação requer dados atualizados e quando o custo de atualizar os dados é inferior ao custo de acedê-los a partir do sistema de backend. No entanto, também pode aumentar a carga no sistema de backend e consumir largura de banda de rede adicional.
Para implementar o padrão Refresh-Ahead, a cache deve atualizar periodicamente os dados através de um trabalho em segundo plano ou de um thread dedicado. A frequência da atualização deve ser cuidadosamente ajustada para equilibrar os benefícios de ter dados atualizados com os custos da sua atualização.
Em alguns casos, pode ser necessário implementar lógica adicional para evitar a atualização excessiva de dados que raramente são acedidos ou que não sofrem alterações frequentemente. Por exemplo, a cache pode usar um tempo de vida (TTL) ou um mecanismo de invalidação de cache para limitar a frequência de atualização de dados.
No geral, o padrão Refresh-Ahead pode ajudar a melhorar o desempenho das aplicações, reduzindo a latência do acesso aos dados e garantindo que dados atualizados estejam prontamente disponíveis. No entanto, requer afinação e gestão cuidadosas para evitar sobrecarregar o sistema de backend ou consumir largura de banda de rede excessiva.
| Padrão | Resumo | Vantagens | Desvantagens |
| Cache-Aside | Os dados são carregados na cache sob demanda, quando solicitados pela aplicação. | Fácil de implementar, baixa taxa de falha de cache. | Latência elevada para a primeira falha de cache, dados desatualizados se não forem invalidados. |
| Leitura Atenta | Os dados são carregados automaticamente na cache quando solicitados pela aplicação. | Baixa latência, preenchimento automático de dados. | Elevada carga na rede e no backend, dados desatualizados se não forem invalidados. |
| Write-Through | Os dados são escritos no cache e no sistema de backend simultaneamente. | Consistência de dados, baixa taxa de falhas de cache. | Latência de escrita elevada, carga de backend elevada. |
| Escrita Criativa | Os dados são gravados no sistema de backend, mas não na cache. | Baixo nível de poluição da cache, baixa latência de escrita. | Latência de leitura elevada para dados frios, sem melhoria de desempenho da cache. |
| Voltar a Escrever | Os dados são gravados na cache e gravados de forma assíncrona no sistema de backend. | Baixa latência de escrita, desempenho de escrita melhorado. | Perda de dados potencial em caso de falha da cache, elevada poluição da cache. |
| Antecipação de Atualização | Os dados são atualizados de forma proativa na cache antes de serem solicitados pela aplicação. | Baixa latência de acesso a dados, dados sempre atualizados. | Elevada carga no backend, potencial congestionamento da rede. |
Cada padrão de cache tem os seus próprios pontos fortes e fracos. A escolha de qual padrão utilizar depende dos requisitos específicos e das características da aplicação. Por exemplo, se a aplicação requer baixa latência para dados acedidos com frequência, os padrões Read-Through ou Cache-Aside podem ser uma boa escolha. Se a consistência dos dados e baixas taxas de falha de cache são importantes, o padrão Write-Through pode ser preferível. Por outro lado, se a aplicação lida com grandes volumes de dados acedidos com pouca frequência, o padrão Write-Around pode ser mais adequado.
Em qualquer caso, é importante avaliar cuidadosamente as contrapartidas de cada padrão de cache e escolher aquele que melhor se adapta às necessidades específicas da aplicação.
Desafios do Caching
Embora o caching possa proporcionar benefícios de desempenho significativos às aplicações, existem vários desafios e dificuldades que devem ser abordados para garantir a sua eficácia.
Tipos de Dados a Armazenar em Cache
A escolha de quais dados armazenar em cache pode ser uma tarefa difícil, já que nem todos os dados são igualmente importantes ou vantajosos para serem armazenados em cache. Armazenar em cache demasiados dados pode resultar em desperdício de recursos e aumento da poluição do cache, enquanto armazenar em cache muito poucos dados pode resultar em altas taxas de falha de cache e redução de desempenho.
Para enfrentar este desafio, é importante avaliar cuidadosamente os padrões de acesso aos dados e as características da aplicação e escolher os dados que são mais acedidos ou que têm o maior impacto no desempenho.
Coerência de Dados
Outro desafio do caching é manter a coerência dos dados, ou garantir que os dados na cache estão consistentes com os dados no sistema de backend. A coerência dos dados é particularmente importante em aplicações que requerem consistência de dados ou que lidam com dados frequentemente atualizados.
Para enfrentar este desafio, devem ser implementados mecanismos de cache que garantam que os dados em cache são atualizados ou invalidados regularmente quando ocorrem alterações no sistema backend. Isto pode incluir a utilização de técnicas como valores de tempo de vida (TTL), invalidação de cache ou a utilização de sistemas de cache distribuído que conseguem sincronizar dados entre múltiplas instâncias de cache.
Ao abordar estes desafios e implementar mecanismos de cache que sejam adaptados às necessidades específicas da aplicação, é possível alcançar melhorias significativas de desempenho e benefícios de escalabilidade.
Vamos Falar Sobre Caching!
A cache pode não ser tão excitante como carros voadores ou teletransporte, mas continua a ser um componente essencial dos sistemas de software modernos. Se procura otimizar o desempenho e a escalabilidade da sua aplicação, o cache é um ótimo ponto de partida.
À AdvanceWorks, temos uma equipa de magos da cache que o pode ajudar a implementar padrões de caching à medida das necessidades específicas da sua aplicação. Do Cache-Aside ao Refresh-Ahead, temos tudo o que precisa.
Portanto, se estiver pronto para levar o desempenho da sua aplicação para o próximo nível, diga-nos! Prometemos não falar em binário ou usar demasiadas siglas.
![]() | Tiago Jordão Arquiteto de Soluções na AdvanceWorks. Sou um arquiteto de software, mas isso é apenas o meu trabalho diurno. À noite, sou um vigilante do controlo de qualidade, certificando-me de que cada linha de código corresponde aos meus padrões rigorosos. Sou também um pouco perfeccionista, mas não se preocupe, estou a trabalhar nisso. |