Teste A/B em Rust: como não quebrar a produção e encontrar a verdade

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que Rust é ideal para testes A/B?

\n

Quando falamos sobre teste A/B, geralmente lembramos de Python, R ou JavaScript. Mas Rust é a carta na manga que, em condições reais de batalha, se mostra mais rápida, segura e barata. Se o seu backend é escrito em Rust, você pode incorporar experimentos diretamente no núcleo do sistema sem a sobrecarga de microsserviços e Redis.

\n

Imagine: você altera o algoritmo de recomendações, a cor do botão "Comprar" ou a lógica de parsing. Um erro no código do teste A/B em Python pode derrubar o servidor. Em Rust — você simplesmente não compila se pular um ramo de condição. O compilador é o seu melhor QA.

\n

Neste artigo, vamos abordar o teste A/B em Rust da arquitetura à produção. Você aprenderá como fazer testes de divisão sem dor, calcular estatísticas e não perder usuários.

\n\n

Arquitetura do teste A/B em Rust: três pilares

\n

Qualquer experimento em uma aplicação Rust se sustenta em três componentes:

\n
    \n
  • Randomizador — quem vai para o grupo A, quem vai para o B?
  • \n
  • Armazenamento de atribuições — para que o usuário não salte entre grupos a cada requisição.
  • \n
  • Registro e estatísticas — calculamos a conversão e o p-value.
  • \n
\n

Vamos escrever um módulo simples, mas funcional. Nada de frameworks — apenas Rust e sua biblioteca padrão.

\n\n

Passo 1. Randomização baseada em hash

\n

Randomização determinística é a chave para a estabilidade. Se você usar rand::random(), a cada reinicialização do servidor o usuário pode pular para outro grupo. Usamos um hash ponderado do ID do usuário e do nome do experimento.

\n\n
use std::collections::hash_map::DefaultHasher;\nuse std::hash::{Hash, Hasher};\n\n#[derive(Debug, Clone, Copy, PartialEq)]\npub enum Group {\n    Control,\n    Treatment,\n}\n\npub fn assign_group(user_id: &str, experiment: &str, treatment_weight: f64) -> Group {\n    let mut hasher = DefaultHasher::new();\n    user_id.hash(&mut hasher);\n    experiment.hash(&mut hasher);\n    let hash = hasher.finish();\n\n    let normalized = (hash as f64) / (u64::MAX as f64);\n    if normalized < treatment_weight {\n        Group::Treatment\n    } else {\n        Group::Control\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_deterministic() {\n        let g1 = assign_group("user_42", "button_color_v2", 0.5);\n        let g2 = assign_group("user_42", "button_color_v2", 0.5);\n        assert_eq!(g1, g2);\n    }\n}\n
\n\n

Este código garante que o mesmo usuário estará sempre no mesmo grupo para um experimento específico. O peso treatment_weight é a fração do tráfego que vai para o grupo de teste (por exemplo, 0.1 = 10%).

\n\n

Passo 2. Armazenamento: cache ou banco de dados?

\n

Para projetos de alta carga, armazenar atribuições em memória é um risco. Se o servidor cair, o usuário perde o grupo. O melhor é usar Redis ou SQLite. Mas, para simplificar, mostraremos um cache in-memory com TTL.

\n\n
use std::collections::HashMap;\nuse std::time::{Duration, Instant};\n\nstruct AssignmentCache {\n    store: HashMap<String, (Group, Instant)>,\n    ttl: Duration,\n}\n\nimpl AssignmentCache {\n    fn new(ttl_secs: u64) -> Self {\n        Self {\n            store: HashMap::new(),\n            ttl: Duration::from_secs(ttl_secs),\n        }\n    }\n\n    fn get(&mut self, key: &str) -> Option<Group> {\n        if let Some((group, time)) = self.store.get(key) {\n            if time.elapsed() < self.ttl {\n                return Some(*group);\n            }\n        }\n        None\n    }\n\n    fn set(&mut self, key: String, group: Group) {\n        self.store.insert(key, (group, Instant::now()));\n    }\n}\n
\n\n

Em um projeto real, substitua HashMap por dashmap ou Redis — isso fornecerá segurança de thread e persistência.

\n\n

Integração com

Blogs

Book Recommendations