Usando Laravel com Dragonfly

Dragonfly é uma substituição drop-in para Redis projetada para oferecer um desempenho muito superior com muito menos servidores. Um único nó pode lidar com milhões de consultas por segundo e até 1TB de dados em memória. Neste artigo, exploraremos como usar o Dragonfly com o Laravel, uma das frameworks web mais amplamente utilizados e conhecidos.

O Dragonfly mantém a compatibilidade total com a interface do Redis, o que significa que os desenvolvedores do Laravel podem integrá-lo como driver de cache e fila sem uma única linha de código alterada. Essa integração perfeita pode oferecer um caminho de atualização sem esforço com benefícios substanciais.

Então, seja você um veterano do Laravel ou apenas começando, junte-se a nós enquanto adentramos o mundo do Dragonfly e Laravel.

Começando

Vamos começar configurando uma nova instância do Dragonfly. Visite nossa documentação aqui para baixar uma imagem ou o binário e ter uma instância do Dragonfly funcionando em pouco tempo. Uma vez que a instância do Dragonfly esteja operacional e acessível, integrar com seu projeto Laravel é uma brisa. Felizmente, o Laravel já tem suporte total para Redis, então todos os seus drivers podem ser reutilizados. Para usar o Dragonfly em seu aplicativo Laravel, comece atualizando o arquivo .env com as seguintes configurações.

Para cache e gerenciamento de sessão:

CACHE_DRIVER=redis
SESSION_DRIVER=redis

Para integrar o Dragonfly como driver de fila também:

QUEUE_CONNECTION=redis

Mesmo que estejamos usando redis como o valor do driver, o Dragonfly foi projetado para ser uma substituição direta para o Redis, portanto, não é necessário instalar nenhum driver adicional. Com o driver configurado, o próximo passo é garantir que o Laravel possa se comunicar com a instância do Dragonfly. Isso envolve atualizar o arquivo .env novamente com os detalhes de conexão corretos:

  • REDIS_HOST: O nome do host ou endereço IP do servidor Dragonfly.
  • REDIS_PORT: A porta na qual a instância Dragonfly está sendo executada.
  • REDIS_PASSWORD: A senha para a instância Dragonfly, se definida.

Aqui está um exemplo de configuração:

REDIS_HOST=127.0.0.1 # Replace with Dragonfly host
REDIS_PORT=6379      # Replace with Dragonfly port
REDIS_PASSWORD=null  # Replace with Dragonfly password if applicable

Após atualizar essas configurações, verifique a conexão executando uma operação simples como INFO no Laravel. Se encontrar algum problema de conectividade, verifique novamente os valores do host, porta e senha. Além disso, certifique-se de que o servidor Dragonfly esteja em execução e acessível a partir do ambiente do aplicativo Laravel.

use Illuminate\Support\Facades\Redis;

// Execute o comando INFO e imprima a versão do Dragonfly.
Redis::info()["dragonfly_version"];

Eficiência Aumentada como Cache

Cachear valores acessados com frequência é uma das principais utilizações de bancos de dados em memória como Dragonfly e Redis, devido aos seus tempos de resposta rápidos. É nesse cenário que o Dragonfly se destaca, especialmente em situações envolvendo um grande número de chaves e clientes, típicas como cache central de sistemas multi-nós ou microservices.

A standout feature of Dragonfly is the cache mode, designed specifically for scenarios where maintaining a lean memory footprint is as crucial as performance. In this mode, Dragonfly evicts the least recently accessed values when it detects low memory availability, ensuring efficient memory usage without sacrificing speed. You can read more about the eviction algorithm in the Dragonfly Cache Design blog post.

Ativar o modo de cache é simples. Aqui estão as flags que você usaria para executar o Dragonfly nesse modo, com um limite de memória de 12GB:

./dragonfly --cache_mode --maxmemory=12G

Considere um cenário em que seu aplicativo precisa lidar com um volume alto de solicitações com um vasto conjunto de dados. Nesses casos, o modo de cache Dragonfly pode gerenciar eficientemente o uso de memória enquanto fornece acesso rápido aos dados, garantindo que seu aplicativo permaneça responsivo e ágil.

Em termos de API, todas as funcionalidades do facade de Cache do Laravel devem ser suportadas. Por exemplo, para armazenar uma determinada chave e valor com um tempo específico de expiração, o seguinte trecho pode ser usado:

use Illuminate\Support\Facades\Cache;

// Armazenar um valor com uma expiração de 10 minutos.
Cache::put("key", "value", 600);

Uso de Memória

Um dos benefícios de usar o Dragonfly como cache é seu uso de memória significativamente menor para a maioria dos casos de uso. Vamos conduzir uma simples experiência e preencher tanto o Redis quanto o Dragonfly com strings aleatórias, medindo seu uso total de memória após preenchê-los com dados.

Dataset Dragonfly Redis
3 Million Values of Length 1000 2.75GB 3.17GB
15 Million Values of Length 200 3.8GB 4.6GB

Após conduzir a experiência, observamos que o uso de memória do Dragonfly é até 20% menor em comparação com o Redis sob condições semelhantes. Isso permite armazenar significativamente mais dados úteis com os mesmos requisitos de memória, tornando o cache mais eficiente e alcançando maior cobertura. Você pode ler mais sobre benchmarks de throughput e uso de memória do Dragonfly no post de blog Redis vs. Dragonfly Scalability and Performance.

Snapshotting

Além do menor uso de memória, o Dragonfly também demonstra estabilidade durante os processos de tiragem de snapshot. Tirar snapshot, especialmente em instâncias ocupadas, pode ser um desafio em termos de gerenciamento de memória. Com o Redis, capturar um snapshot em uma instância altamente ativa pode levar a um aumento no uso de memória. Isso ocorre porque o Redis precisa copiar páginas de memória, mesmo aquelas que foram apenas parcialmente sobrescritas, resultando em um pico no uso de memória.

Em contraste, o Dragonfly ajusta a ordem da tiragem de snapshot com base nas solicitações recebidas, efetivamente impedindo qualquer aumento inesperado no uso de memória. Isso significa que mesmo durante operações intensivas como a tiragem de snapshot, o Dragonfly mantém uma pegada de memória estável, garantindo um desempenho consistente sem o risco de picos súbitos de memória. Você pode ler mais sobre o algoritmo de tiragem de snapshot do Dragonfly no artigo “Balanced vs. Unbalanced”.

Stickiness de Chave

O Dragonfly também introduz um novo recurso com seu comando personalizado STICK. Esse comando é particularmente útil em instâncias que operam no modo de cache. Ele permite marcar chaves específicas como não-evitáveis, independentemente de sua frequência de acesso.

Essa funcionalidade é particularmente útil para armazenar dados importantes, mas raramente acessados. Por exemplo, você pode manter de forma confiável informações auxiliares, como valores de configuração dinâmica, diretamente em sua instância do Dragonfly. Isso elimina a necessidade de um datastore separado para dados utilizados com pouca frequência, mas cruciais, simplificando o processo de gerenciamento de dados.

// Armazenando um valor na instância do Dragonfly com persistência.
Redis::transaction(function (Redis $redis) {
    $redis->set('server-dynamic-configuration-key', '...');
    $redis->command('STICK', 'server-dynamic-configuration-key');
});

// ...

// Sempre retornará um valor, pois a chave não pode ser evicada.
$redis->get('server-dynamic-configuration-key');

Aumento da Capacidade de Processamento em Gerenciamento de Fila

O Dragonfly, muito parecido com o Redis, é habilidoso em gerenciar filas e tarefas. Como você já deve ter adivinhado, a transição para usar o Dragonfly para esse propósito é suave, não exigindo modificações de código. Considere o seguinte exemplo no Laravel, onde uma tarefa de processamento de podcast é despachada:

use App\Jobs\ProcessPodcast;

$podcast = Podcast::create(/* ... */);
ProcessPodcast::dispatchSync($podcast);

Tanto o Dragonfly quanto o Redis são capazes de lidar com dezenas de milhares de tarefas por segundo com facilidade.

Para aqueles que desejam maximizar o desempenho, é importante notar que usar uma única fila de tarefas não resultará em ganhos de desempenho significativos. Para realmente aproveitar as capacidades do Dragonfly, devem ser utilizadas múltiplas filas. Essa abordagem distribui a carga em vários threads do Dragonfly, aumentando a capacidade de processamento geral.

No entanto, surge um desafio comum quando chaves da mesma fila acabam em diferentes threads, o que leva a um aumento na latência. Para combater isso, o Dragonfly oferece o uso de hashtags em nomes de fila. Esses hashtags garantem que tarefas na mesma fila (que usa o mesmo hashtag) sejam automaticamente atribuídas a threads específicos, muito parecido com um ambiente de Cluster Redis, reduzindo a latência e otimizando o desempenho. Para saber mais sobre hashtags, dê uma olhada no post do blog Executando BullMQ com Dragonfly, que tem uma explicação detalhada sobre hashtags e seus benefícios, enquanto o Dragonfly é usado como armazenamento de suporte para sistemas de fila de mensagens.

Como um exemplo rápido, para otimizar a gestão de suas filas com o Dragonfly, comece lançando o Dragonfly com bandeiras específicas que habilitam bloqueio baseado em hashtag e modo de cluster emulado:

./dragonfly --lock_on_hashtags --cluster_mode=emulated

Uma vez que o Dragonfly esteja em execução com essas configurações, incorpore hashtags em seus nomes de fila no Laravel. Aqui está um exemplo:

ProcessPodcast::dispatch($podcast)->onQueue('{podcast_queue}');

Ao usar hashtags em nomes de fila, você garante que todas as mensagens pertencentes à mesma fila sejam processadas pelo mesmo thread no Dragonfly. Essa abordagem não apenas mantém mensagens relacionadas juntas, melhorando a eficiência, mas também permite que o Dragonfly maximize a taxa de transferência distribuindo filas diferentes em vários threads.

Este método é particularmente eficaz para sistemas que dependem do Dragonfly como repositório de filas de mensagens, pois aproveita a arquitetura multi-threaded do Dragonfly para lidar com um volume maior de mensagens de forma mais eficiente.

Conclusão

A capacidade do Dragonfly de lidar com cargas de trabalho massivas com menor uso de memória e sua arquitetura multi-threaded tornam-no uma escolha atraente para aplicativos web modernos. Ao longo deste artigo, exploramos como o Dragonfly se integra perfeitamente com o Laravel, exigindo mudanças mínimas ou nenhuma no código, seja para cache, gerenciamento de sessão ou gerenciamento de filas.

Source:
https://dzone.com/articles/using-laravel-with-dragonfly