Defective Code Logo

Total Downloads Latest Stable Version Latest Stable Version

English | العربية | বাংলা | Bosanski | Deutsch | Español | Français | हिन्दी | Italiano | 日本語 | 한국어 | मराठी | Português | Русский | Kiswahili | தமிழ் | తెలుగు | Türkçe | اردو | Tiếng Việt | 中文

Introdução

Recall é um pacote de caching de alto desempenho do lado do cliente Redis para Laravel. Ele utiliza o recurso de caching do lado do cliente do Redis 6 com invalidação automática para reduzir drasticamente as idas e voltas ao Redis e a latência. Desenvolvido especificamente para ambientes Laravel Octane, ele usa APCu ou Swoole Table como uma camada de cache local que permanece sincronizada com o Redis por meio de mensagens de invalidação.

Quando você busca um valor do Redis, o Recall armazena-o localmente. Quando esse valor muda no Redis (de qualquer cliente), o Redis notifica automaticamente o Recall para invalidar a cópia local. Isso proporciona a velocidade do caching em memória com as garantias de consistência do Redis.

Principais Características

Exemplo

// Configure recall como seu driver de cache
// config/cache.php
'stores' => [
'recall' => [
'driver' => 'recall',
],
],
 
// Use como qualquer cache do Laravel
use Illuminate\Support\Facades\Cache;
 
// Primeira chamada: busca do Redis, armazena localmente
$user = Cache::store('recall')->get('user:1');
 
// Chamadas subsequentes: servidas do APCu/Swoole Table local (microsegundos)
$user = Cache::store('recall')->get('user:1');
 
// Quando user:1 é atualizado em qualquer lugar, o Redis notifica o Recall para invalidar
Cache::store('recall')->put('user:1', $newUserData, 3600);
// O cache local é automaticamente invalidado em todos os workers

Instalação

Instale o pacote via Composer:

composer require defectivecode/laravel-recall

Requisitos

Uso

Configuração Básica

  1. Adicione o armazenamento de cache do Recall ao seu config/cache.php:
'stores' => [
// ... outros armazenamentos
 
'recall' => [
'driver' => 'recall',
],
],
  1. Use o armazenamento de cache em sua aplicação:
use Illuminate\Support\Facades\Cache;
 
// Armazene um valor (grava no Redis)
Cache::store('recall')->put('key', 'value', 3600);
 
// Recupere um valor (a primeira chamada atinge o Redis, chamadas subsequentes usam o cache local)
$value = Cache::store('recall')->get('key');
 
// Delete um valor
Cache::store('recall')->forget('key');

Como Funciona

  1. Primeira Leitura: O valor é buscado no Redis e armazenado no cache local APCu/Swoole Table.
  2. Leituras Subsequentemente: O valor é servido diretamente da memória local (sub-milisegundos).
  3. Escrita em Qualquer Lugar: Quando qualquer cliente modifica a chave no Redis, o Redis envia uma mensagem de invalidação.
  4. Invalidação Automática: O Recall recebe a mensagem e remove a chave do cache local.
  5. Próxima Leitura: Um novo valor é buscado do Redis e armazenado novamente localmente.

Esse padrão é especialmente poderoso em ambientes Laravel Octane, onde os workers persistem entre as requisições, permitindo que o cache local se acumule e sirva muitas requisições a partir da memória.

Integração com Octane

O Recall se integra automaticamente ao Laravel Octane quando disponível:

Nenhuma configuração adicional é necessária. A integração é automática quando o Octane está instalado.

Configuração

Publique o arquivo de configuração:

php artisan vendor:publish --tag=recall-config

Isso cria o config/recall.php com as seguintes opções:

Habilitar/Desabilitar

'enabled' => env('RECALL_ENABLED', true),

Quando desativado, o Recall passa diretamente para o Redis sem usar a camada de cache local. Útil para depuração ou rolagem gradual.

Armazenamento Redis

'redis_store' => env('RECALL_REDIS_STORE', 'redis'),

O armazenamento de cache do Laravel a ser usado para operações do Redis. Isso deve referenciar um armazenamento Redis configurado em seu config/cache.php.

Prefixos de Cache

'cache_prefixes' => [],

Armazene localmente apenas chaves que correspondem a esses prefixos. Deixe vazio para armazenar todas as chaves.

// Armazene localmente apenas chaves de usuário e configurações
'cache_prefixes' => ['users:', 'settings:', 'config:'],

Isso é útil quando você tem chaves de alto volume que mudam com frequência e não deveriam ser armazenadas localmente.

Configuração do Cache Local

'local_cache' => [
// Driver: "apcu" ou "swoole"
'driver' => env('RECALL_LOCAL_DRIVER', 'apcu'),
 
// Prefixo para chaves de cache local
'key_prefix' => env('RECALL_LOCAL_PREFIX', 'recall:'),
 
// TTL padrão em segundos (rede de segurança se a invalidação for perdida)
'default_ttl' => (int) env('RECALL_LOCAL_TTL', 3600),
 
// Tamanho da Swoole Table (potência de 2, apenas para driver swoole)
'table_size' => (int) env('RECALL_SWOOLE_TABLE_SIZE', 65536),
 
// Máximo de bytes por valor na Swoole Table (apenas para driver swoole)
'value_size' => (int) env('RECALL_SWOOLE_VALUE_SIZE', 8192),
],

Driver APCu (Padrão)

O driver APCu funciona com todos os ambientes PHP e servidores Octane (Swoole, RoadRunner, FrankenPHP). Ele armazena os valores em cache na memória compartilhada acessível a todos os processos PHP.

Requisitos:

Driver Swoole Table

O driver Swoole Table utiliza tabelas de memória compartilhada do Swoole, proporcionando acesso consistente entre corrotinas dentro do mesmo worker. Melhor para ambientes Swoole/OpenSwoole.

Dicas de configuração:

Listeners do Octane

'listeners' => [
// Aquecer conexão ao iniciar o worker (reduz a latência da primeira requisição)
'warm' => env('RECALL_LISTEN_WARM', true),
 
// Processar invalidações em eventos de tick (mais responsivo, leve sobrecarga)
'tick' => env('RECALL_LISTEN_TICK', false),
],

Conexões Aquecidas

Quando ativado, o Recall estabelece a assinatura de invalidação do Redis quando o worker Octane inicia. Isso elimina a latência de conexão na primeira requisição.

Processamento de Tick

Quando ativado, o Recall processa mensagens de invalidação em eventos de tick do Octane além de eventos de requisição. Isso proporciona uma invalidação de cache mais responsiva com o custo de uma leve sobrecarga adicional.

Uso Avançado

Processamento Manual de Invalidações

Se você precisar processar invalidações manualmente (por exemplo, em um processo de longa duração):

use DefectiveCode\Recall\RecallManager;
 
$manager = app(RecallManager::class);
$manager->processInvalidations();

Limpeza do Cache Local

Para limpar apenas o cache local sem afetar o Redis:

use DefectiveCode\Recall\RecallManager;
 
$manager = app(RecallManager::class);
$manager->flushLocalCache();

Gerenciamento de Conexões

use DefectiveCode\Recall\RecallManager;
 
$manager = app(RecallManager::class);
 
// Verifique se a assinatura de invalidação está conectada
if ($manager->isConnected()) {
// ...
}
 
// Desconectar manualmente
$manager->disconnect();

Otimização

Limites de Requisições de Worker

O Laravel Octane faz ciclos nos workers após um número configurável de requisições para prevenir vazamentos de memória. Quando um worker roda, seu cache local é limpo. Aumentar esse limite permite que o cache local do Recall persista mais tempo, melhorando as taxas de acerto do cache.

No seu config/octane.php:

// O padrão é 500 requisições antes de reiniciar
'max_requests' => 10000,

Valores mais altos significam melhor utilização do cache, mas requer confiança de que sua aplicação não tem vazamentos de memória. Monitore o uso de memória do seu worker ao ajustar esse valor.

Caching Seletivo com Prefixos

Use cache_prefixes para controlar quais chaves são armazenadas localmente. Isso é valioso quando:

// config/recall.php
'cache_prefixes' => [
'users:', // Armazene dados do usuário localmente
'settings:', // Armazene configurações da aplicação
'products:', // Armazene catálogo de produtos
],

Chaves que não correspondem a esses prefixos ainda funcionarão, mas evitarão o caching local, indo diretamente para o Redis.

Considerações de Memória

Memória APCu

APCu compartilha memória entre todos os processos PHP. Configure o limite de memória em php.ini:

; O padrão é 32MB, aumente para necessidades de cache maiores
apc.shm_size = 128M

Monitore o uso do APCu com apcu_cache_info():

$info = apcu_cache_info();
$memory = $info['mem_size']; // Uso atual de memória em bytes

Dimensionamento da Tabela Swoole

As Tabelas Swoole têm capacidade fixa configurada na criação. Planeje para o seu tamanho de cache esperado:

'local_cache' => [
// Máximo de entradas (deve ser potência de 2)
'table_size' => 65536, // 64K entradas
 
// Tamanho máximo de valor serializado em bytes
'value_size' => 8192, // 8KB por valor
],

Uso de memória: table_size × (value_size + overhead). Uma tabela com 65536 entradas e valores de 8KB usa aproximadamente 512MB.

Padrões Comuns

Configuração da Aplicação

// Cache de flags de recursos e configurações
$features = Cache::store('recall')->remember('config:features', 3600, function () {
return Feature::all()->pluck('enabled', 'name')->toArray();
});
 
// Quando as configurações mudam, todos os workers recebem automaticamente as atualizações

Dados de Referência Acessados com Frequência

// Cache de categorias de produtos
$categories = Cache::store('recall')->remember('categories:all', 3600, function () {
return Category::with('children')->whereNull('parent_id')->get();
});
 
// Cache de taxas de câmbio
$rates = Cache::store('recall')->remember('rates:exchange', 300, function () {
return ExchangeRate::all()->pluck('rate', 'currency')->toArray();
});

Alternativa a Tags de Cache

O Recall não suporta tags de cache, mas você pode alcançar funcionalidade semelhante com prefixos:

// Em vez de tags, use prefixos consistentes
Cache::store('recall')->put("blog:posts:{$id}", $post, 3600);
Cache::store('recall')->put("blog:comments:{$postId}", $comments, 3600);
 
// Limpe todo o cache relacionado a blogs pelo prefixo (requer implementação manual)
// Ou confie na invalidação automática quando os dados mudam

Limitações

Modo Cluster do Redis

O Recall não suporta o modo Cluster do Redis. A opção REDIRECT do comando CLIENT TRACKING requer que tanto a conexão de dados quanto a conexão de assinante de invalidação estejam no mesmo nó do Redis. Em um cluster, as chaves são distribuídas por múltiplos nós com base em slots de hash, tornando impossível receber invalidações para chaves armazenadas em diferentes nós.

Para implantações de Redis em cluster, considere:

Diretrizes de Suporte

Obrigado por escolher nosso pacote de código aberto! Por favor, reserve um momento para conferir estas diretrizes de suporte. Elas ajudarão você a aproveitar ao máximo nosso projeto.

Suporte Direcionado pela Comunidade

Nosso projeto de código aberto é alimentado por nossa incrível comunidade. Se você tiver dúvidas ou precisar de assistência, StackOverflow e outros recursos online são suas melhores opções.

Erros e Priorização de Recursos

A realidade de gerenciar um projeto de código aberto significa que não podemos abordar imediatamente todos os erros ou solicitações de recursos relatados. Priorizamos as questões na seguinte ordem:

1. Erros que Afetam Nossos Produtos Pagos

Erros que impactam nossos produtos pagos serão sempre nossa maior prioridade. Em alguns casos, podemos abordar apenas erros que nos afetam diretamente.

2. Pull Requests da Comunidade

Se você identificou um erro e tem uma solução, por favor, envie um pull request. Após as questões que afetam nossos produtos, damos a próxima maior prioridade a essas correções impulsionadas pela comunidade. Uma vez revisada e aprovada, iremos mesclar sua solução e creditar sua contribuição.

3. Apoio Financeiro

Para questões fora das categorias mencionadas, você pode optar por financiar sua resolução. Cada problema em aberto está vinculado a um formulário de pedido onde você pode contribuir financeiramente. Priorizamos essas questões com base no valor do financiamento fornecido.

Contribuições da Comunidade

O código aberto prospera quando sua comunidade é ativa. Mesmo que você não esteja corrigindo erros, considere contribuir com melhorias de código, atualizações de documentação, tutoriais ou ajudando outros em canais da comunidade. Incentivamos fortemente todos, como comunidade, a ajudar a apoiar o trabalho de código aberto.

Para reiterar, a DefectiveCode priorizará erros com base em como eles impactam nossos produtos pagos, pull requests da comunidade e o apoio financeiro recebido para as questões.

Licença - Licença MIT

Copyright © Defective Code, LLC. Todos os direitos reservados

A permissão é concedida, sem qualquer custo, a qualquer pessoa que obter uma cópia deste software e dos arquivos de documentação associados (o "Software"), para lidar com o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, fundir, publicar, distribuir, sublicenciar e/ou vender cópias do Software, e para permitir que pessoas a quem o Software é fornecido façam o mesmo, sujeito às seguintes condições:

O aviso de copyright acima e este aviso de permissão devem ser incluídos em todas as cópias ou porções substanciais do Software.

O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM FIM ESPECÍFICO E NÃO INFRAÇÃO. EM NENHUM CASO OS AUTORES OU DETENTORES DO DIREITO AUTORAL SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, DELITO OU DE OUTRA FORMA, DECORRENTES DE, EM DECORRÊNCIA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.