Marcio Cunha

Rate Limiting Distribuído em Serverless com Token Bucket e Redis Cluster

Descubra como implementar controle de tráfego escalável em arquiteturas serverless usando o algoritmo Token Bucket integrado a um cluster Redis distribuído.

Marcio Cunha•4 min
Também disponível em:EnglishEspañol
Resumo
  • Sistemas sem servidores dedicados exigem contadores externos para gerenciar tráfego porque escalam de forma imprevisível.
  • O algoritmo Token Bucket permite picos controlados de acesso sem penalizar imediatamente usuários legítimos.
  • O Redis Cluster distribui chaves de controle em múltiplas máquinas para evitar gargalos de performance.
  • Scripts Lua executados diretamente no banco de dados garantem operações atômicas sem condições de corrida.
  • A latência de rede entre funções efêmeras e nós de cache exige estratégias inteligentes de resiliência e fallback.

O Desafio do Controle de Tráfego em Funções Efêmeras

Quando construímos aplicações modernas usando funções sem servidores dedicados — conhecidas na engenharia como arquiteturas serverless —, o código acorda para atender a uma requisição e dorme logo em seguida. Na prática, isso significa que não temos uma memória centralizada rodando em uma máquina fixa para contar quantas vezes um usuário acessou o sistema. Cada requisição pode cair em um contêiner diferente espalhado pelo mundo, tornando o controle de tráfego um quebra-cabeça de engenharia fascinante.

Se um robô mal intencionado decide derrubar sua API disparando milhares de chamadas por segundo, o provedor de nuvem vai criar milhares de funções para tentar atender a todos, gerando uma conta astronômica no final do mês. Para evitar esse pesadelo financeiro e manter o serviço estável, precisamos de um mecanismo de rate limiting, ou seja, um porteiro digital inteligente que decide quem entra e quem fica na fila de espera com base em regras rígidas de consumo.

Entendendo a Dinâmica do Token Bucket

Existem várias formas de limitar o tráfego, mas o algoritmo conhecido como Token Bucket se destaca pela flexibilidade. Imagine um balde que recebe fichas a cada segundo de forma constante até atingir um limite máximo. Cada vez que um usuário faz uma requisição, o sistema retira uma ficha desse balde. Na prática, isso significa que se o balde tiver fichas, a requisição passa imediatamente; se estiver vazio, o acesso é bloqueado ou colocado em espera.

A grande vantagem desse modelo sobre contadores simples de tempo fixo é a tolerância a picos legítimos de uso. Se um usuário clica em vários botões rapidamente, ele consome as fichas acumuladas durante o período de ociosidade, sem ser barrado injustamente. Para implementar isso em larga escala, precisamos de um banco de dados em memória ultrarrápido que consiga atualizar e ler essas fichas em microssegundos, e é aí que entra o Redis.

Por Que o Redis Cluster se Torna a Escolha Ideal

O Redis é um armazenamento de dados baseado em memória RAM que responde a consultas quase instantaneamente, funcionando como uma central de recados ultrarrápida. Quando operamos em ambientes corporativos de altíssimo tráfego, um único servidor Redis pode virar o gargalo ou sofrer uma pane por excesso de trabalho. É nesse cenário que adotamos o Redis Cluster, uma topologia que divide os dados em vários nós independentes interligados.

Na prática, o cluster espalha os baldes de fichas dos diferentes usuários por várias máquinas diferentes. Isso garante alta disponibilidade e resiliência: se um dos servidores do cluster falhar por algum motivo, o restante do sistema continua operando sem derrubar a aplicação inteira. Contudo, coordenar chaves distribuídas exige atenção redobrada para evitar inconsistências matemáticas no saldo de fichas.

Garantindo Consistência Atômica com Scripts Lua

O maior perigo em sistemas distribuídos é a famosa condição de corrida, que acontece quando duas requisições do mesmo usuário chegam exatamente no mesmo milissegundo em nós diferentes do Redis. Se ambas lerem o saldo de fichas antes de qualquer atualização, o sistema pode permitir o dobro do limite autorizado. Para resolver esse problema sem travar o sistema inteiro, utilizamos scripts escritos na linguagem Lua rodando diretamente dentro do próprio Redis.

Na prática, o script Lua funciona como uma caixa preta inquebrável: o Redis executa todas as instruções do script de uma só vez, do começo ao fim, sem permitir que nenhuma outra operação se intrometa no meio do caminho. Isso garante atomicidade, assegurando que o cálculo de recarga e dedução de fichas ocorra de forma perfeitamente sincronizada, independentemente da quantidade de instâncias chamando o banco ao mesmo tempo.

Resiliência, Falhas Silenciosas e Estratégias de Fallback

Nenhuma arquitetura de nuvem é imune a falhas de rede ou quedas temporárias de infraestrutura. Se o nosso cluster Redis ficar inacessível por alguns segundos devido a uma manutenção ou instabilidade, a nossa API não pode simplesmente parar de funcionar e recusar todos os clientes legítimos. Precisamos planejar estratégias de fallback, que funcionam como um plano de escape quando o sistema principal falha.

Na prática, configuramos o código da função serverless para detectar falhas de conexão com o Redis após um limite rigoroso de tempo, como cinquenta milissegundos. Se o banco falhar, o sistema assume um modo tolerante e permite a passagem do tráfego temporariamente, priorizando a disponibilidade do negócio em vez de bloquear o usuário por causa de um problema interno de infraestrutura.

Considerações Finais sobre Escalabilidade e Controle

Desenvolver uma estratégia robusta de controle de tráfego em arquiteturas serverless exige equilibrar velocidade, precisão matemática e tolerância a falhas. O uso combinado do algoritmo Token Bucket com um cluster Redis distribuído oferece uma solução madura para suportar milhões de requisições sem comprometer o orçamento de nuvem ou a experiência do usuário. O segredo do sucesso reside na simplicidade operacional e no uso correto de operações atômicas em memória.