O cache de página inteira (Full Page Cache) é excelente para blogs estáticos, mas falha miseravelmente em sites dinâmicos como lojas WooCommerce ou portais de membros.
Quando um usuário faz login, a página não pode mais ser servida estaticamente, obrigando o PHP a processar tudo novamente.
A solução arquitetural para este problema é o Cache de Fragmentos (Fragment Caching).
Com esta técnica, nós armazenamos apenas blocos específicos de HTML, como o cabeçalho complexo, a lista de categorias ou widgets pesados.
O restante da página permanece dinâmico.
Nesta masterclass, construiremos um sistema avançado de Fragment Caching nativo, mas com um diferencial técnico de peso: a proteção contra o efeito “Cache Stampede”.
Esta é uma das falhas mais silenciosas e destrutivas em sistemas de alta disponibilidade.
A Anatomia da Avalanche: O que é Cache Stampede?
O problema do Cache Stampede (Estouro de Manada) ocorre no exato milissegundo em que uma chave de cache pesada expira.
Se o seu site recebe centenas de visitas por segundo, e o cache do “Mega Menu” expira, todas essas centenas de requisições vão tentar regenerar o cache ao mesmo tempo.
Isso causará centenas de consultas idênticas no banco de dados MySQL simultaneamente.
O resultado imediato é um pico extremo de uso de CPU e um provável travamento do servidor (Downtime).
Em um ambiente mal estruturado, o servidor fica preso em um loop de travamentos sucessivos.
A solução ingênua seria aumentar o tempo de vida do cache (TTL), mas isso não previne o stampede, apenas adia o desastre.
A Solução: Algoritmo de Expiração Antecipada Probabilística
Para resolver este problema complexo, utilizaremos um conceito matemático chamado XFetch ou Expiração Antecipada Probabilística (Probabilistic Early Expiration).
A lógica consiste em fazer com que uma pequena porcentagem das requisições recrie o cache antes mesmo de ele expirar de fato.
Conforme o tempo de expiração se aproxima, a probabilidade de uma requisição ser escolhida para regenerar os dados aumenta.
Isso garante que apenas um único processo realize o trabalho pesado, enquanto os outros usuários continuam recebendo a versão antiga que ainda está na memória.
É uma técnica elegante e matematicamente sólida, amplamente utilizada por engenheiros do Google e do Facebook.
A implementação exige o domínio do sistema de Transients ou Object Cache nativo do WordPress.
// Implementação Sênior do Fragment Cache com XFetch
class FragmentCacheStampede {
private const BETA = 1.0; // Fator de ajuste probabilístico
public static function get_fragment(string $key, callable $generator, int $ttl = 3600): string {
$cache_key = "frag_cache_" . md5($key);
$cached_data = wp_cache_get($cache_key, 'mundo_php');
$now = microtime(true);
if ($cached_data !== false) {
$delta = $cached_data['computation_time'];
$expiry = $cached_data['expiry'];
// Cálculo da Expiração Antecipada Probabilística
if ($now - $delta * self::BETA * log(rand() / getrandmax()) >= $expiry) {
// Sorteado para recriar o cache antecipadamente
return self::regenerate_and_save($cache_key, $generator, $ttl);
}
return $cached_data['html'];
}
// Se não existir nada, cria obrigatoriamente
return self::regenerate_and_save($cache_key, $generator, $ttl);
}
private static function regenerate_and_save(string $key, callable $generator, int $ttl): string {
$start = microtime(true);
// Output buffering para capturar o HTML gerado pelo callback
ob_start();
call_user_func($generator);
$html = ob_get_clean();
$computation_time = microtime(true) - $start;
$data_to_store = [
'html' => $html,
'computation_time' => $computation_time,
'expiry' => microtime(true) + $ttl
];
// Armazenamos por mais tempo do que o TTL lógico para evitar o stampede
wp_cache_set($key, $data_to_store, 'mundo_php', $ttl + 300);
return $html;
}
}
Aplicações Práticas no Tema do WordPress
Agora que a classe do framework está pronta, a aplicação prática dentro do seu tema ou plugin torna-se um exercício de limpeza de código.
Sempre que você tiver uma estrutura de menu pesado ou uma listagem de categorias que requer múltiplos JOINs no MySQL, basta envolvê-la na chamada da nossa classe.
Passamos a chave única do fragmento e uma função anônima (callback) que gera o HTML.
A beleza do Output Buffering (ob_start) nativo do PHP é que você pode usar os comandos tradicionais do WordPress, como get_template_part ou laços while dentro da função geradora.
O cache capturará toda a saída visual de forma totalmente transparente.
// Usando o Fragment Cache no seu header.php
$menu_html = FragmentCacheStampede::get_fragment(
'header_mega_menu_users',
function() {
// Esta query pesada só rodará probabilisticamente
$categories = get_terms([
'taxonomy' => 'product_cat',
'hide_empty' => false,
'meta_query' => [ /* regras de negócio densas */ ]
]);
echo "";
},
7200 // O TTL lógico é de 2 horas
);
echo $menu_html;
Considerações sobre Invalidação de Cache
Phil Karlton, pioneiro da Netscape, disse famosamente: “Existem apenas duas coisas difíceis na Ciência da Computação: invalidação de cache e dar nomes às coisas”.
Nossa aplicação baseada em tempo (TTL) é resiliente, mas e se o administrador do site editar uma categoria de produto?
Não queremos que o usuário espere duas horas para ver o menu atualizado.
A abordagem sênior é utilizar “Event-Driven Invalidation” (Invalidação Guiada por Eventos).
Você deve engatar ações (hooks) nos eventos de salvamento do WordPress, como edit_term ou save_post, e deletar fisicamente a chave do objeto armazenado via wp_cache_delete.
Isso força o sistema a recriar o fragmento na próxima visita de imediato.
A Importância do Object Cache Backend
Para que o método wp_cache_set do WordPress funcione com essa lógica complexa sem penalizar o banco de dados MySQL, você é obrigado a ter um Object Cache configurado no servidor.
Redis ou Memcached atuam como o motor por trás dessa camada de abstração do CMS.
Se você utilizar a nossa classe em um ambiente sem um backend de cache em RAM, os dados não persistirão adequadamente ou, se substituídos por Transients (que salvam na tabela wp_options), acabarão criando um gargalo relacional no disco rígido SSD.
Portanto, a integração DevOps da sua hospedagem é fundamental.
Um desenvolvedor sênior entende que o código PHP e o hardware do servidor são sistemas simbióticos.
Aprender a orquestrar essa simbiose é a sua principal missão.


