Shopify Redis: Migração para MySQL aumenta escalabilidade
Descubra como a Shopify trocou Redis por MySQL para reservas de estoque, melhorando consistência e escala. Saiba mais agora.
Introdução
A Shopify é conhecida por sua infraestrutura de alta disponibilidade, capaz de suportar milhões de pedidos diariamente. Um dos pontos críticos para o e-commerce é a reserva de estoque em tempo real, fundamental para evitar o oversell e garantir uma boa experiência ao cliente. Tradicionalmente, a plataforma utilizava o Redis — um banco de dados em memória — para armazenar esses estados temporários. No entanto, desafios relacionados à consistência e à complexidade do escalonamento levaram a uma reavaliação dessa abordagem.
O Desafio
- Consistência eventual: O Redis oferece consistência forte apenas em cenários single-node; em clusters, a replicação pode introduzir latência.
- Escalabilidade de dados: À medida que a base de usuários cresceu, a quantidade de chaves no Redis aumentou exponencialmente, exigindo mais nós e elevando a complexidade do sharding.
- Operações de leitura e escrita: As reservas de estoque exigem leituras rápidas e atualizações atômicas, além de necessitarem de histórico para auditorias e relatórios.
Por que o Redis?
O Redis era escolhido por sua velocidade (armazenamento em memória) e pela facilidade de implementação de locks distribuídos. Porém, com o crescimento da Shopify, a necessidade de persistência, transações multilinha e consultas analíticas tornou o Redis insuficiente.
A Mudança para o MySQL
A equipe optou por migrar para o MySQL 8.0, aproveitando recursos como:
- Transações ACID: Garantia de consistência em todas as operações.
- Índices avançados: Consultas mais rápidas em tabelas de estoque.
- Particionamento: Distribuição de dados por região ou SKU.
A estratégia incluiu:
1. Replica set para alta disponibilidade.
2. Cache em memória (Redis) apenas para consultas de leitura frequentes, reduzindo a carga no banco de dados.
3. Fila de eventos (Kafka) para sincronizar atualizações de estoque em tempo real.
Arquitetura Pós-Mudança
Usuário → API → Serviço de Reserva → MySQL (Transação) → Kafka → Serviço de Atualização de Estoque → Cache Redis (Leitura)
O serviço de reserva grava a transação no MySQL e publica um evento no Kafka, que atualiza o estoque e, em seguida, atualiza o cache no Redis para garantir respostas rápidas.
Escalabilidade e Desempenho
- Throughput: Mesmo processando mais de 1 milhão de pedidos por dia, o sistema manteve a latência abaixo de 200 ms.
- Consistência: Garantia de que nenhum SKU seja vendido em quantidade superior à disponível.
- Custos: Redução de 30% nos recursos de memória, já que o Redis passou a atuar apenas como cache de leitura.
Exemplos de Código
Transação MySQL (Ruby on Rails)
ruby
ActiveRecord::Base.transaction do
sku = Inventory.find_by!(sku: 'ABC123')
raise 'Estoque insuficiente' if sku.quantity < 1
sku.update!(quantity: sku.quantity - 1)
Reservation.create!(sku: sku, quantity: 1, user_id: current_user.id)
end
Publicação Kafka (Node.js)
js
producer.send({
topic: 'inventory_updates',
messages: [{ key: 'ABC123', value: JSON.stringify({ delta: -1 }) }]
});
Lições Aprendidas
- Persistência vs. velocidade: Quando a consistência é crítica, o armazenamento apenas em memória pode não ser suficiente.
- Camada de cache: Usar o Redis exclusivamente para leitura evita a sobrecarga nas operações de escrita.
- Mensageria: O Kafka garante a consistência eventual entre microserviços.
Conclusão Prática
Para e-commerces que enfrentam um crescimento exponencial, a migração do Redis para o MySQL, combinada com uma camada de cache e mensageria, oferece consistência, escalabilidade e custos controlados. Avalie a criticidade de cada operação: se a transação precisa ser atômica, opte por um banco relacional; se for necessária apenas uma leitura rápida, mantenha o cache em memória. A experiência da Shopify demonstra que, com a arquitetura correta, é possível processar milhões de pedidos mantendo a integridade do estoque.