Designing Data-Intensive Applications: Capítulo 1
Os sistemas de software consomem cada vez mais dados, e precisam estar disponíveis 24h por dia. Vamos descobrir como podemos projetar sistemas assim.
Em 2017, Martin Kleppmann publicou "Designing Data-Intensive Applications" (DDIA), hoje considerado leitura obrigatória para engenheiros de software que trabalham com sistemas distribuídos.
Por que esse livro se tornou tão importante? Porque ele consegue algo raro: traduz conceitos complexos de sistemas distribuídos em princípios práticos e acionáveis.
Hoje começamos uma série especial aqui no Dev na Gringa focada em system design. A cada 2-3 semanas, exploraremos arquiteturas de sistemas distribuídos, sempre com exemplos práticos e casos reais.
E começamos essa jornada explorando o DDIA, capítulo por capítulo.
Neste primeiro artigo da série, vamos cobrir os fundamentos apresentados no Capítulo 1 do DDIA: confiabilidade, escalabilidade e manutenibilidade. São conceitos que formam a base para entender todo o resto do livro.
O conteúdo do livro é muito rico e vale uma leitura mais aprofundada para todos. Meu objetivo não é substituí-lo, mas sim resumir os principais pontos elaborados durante cada capítulo.
✨ O que esperar do artigo
Como as aplicações modernas evoluíram de compute-intensive para data-intensive
Os componentes fundamentais de sistemas de dados modernos
Por que precisamos repensar como construímos aplicações hoje
A Evolução Para Sistemas Data-Intensive
Nos últimos anos, o cenário de desenvolvimento de software mudou drasticamente:
Google, Meta, e Amazon lidam com volumes imensos de dados
CPUs não ficam muito mais rápidas, mas temos mais cores
Infraestrutura cloud permite distribuir sistemas globalmente
Usuários esperam 100% de disponibilidade
O resultado? O dado se tornou nosso maior desafio, não o processamento.
Uma aplicação é considerada data-intensive quando dados são seu principal desafio, seja por:
Volume: quantidade de dados
Complexidade: como os dados se relacionam
Velocidade: taxa de mudança dos dados
Por exemplo: o Uber processa:
20-30 milhões de viagens por dia
Localização em tempo real de milhões de motoristas
Dados históricos para previsão de preços
Avaliações e feedback de usuários
Todos esses são desafios de dados, não de processamento.
Os Blocos Fundamentais de Sistemas Modernos
Toda aplicação data-intensive é construída combinando ferramentas especializadas:
1. Bancos de Dados
Armazenam dados para consulta posterior
Diferentes tipos para diferentes casos de uso
Exemplo: PostgreSQL para dados relacionais, MongoDB para documentos
2. Caches
Aceleram leituras guardando resultados
Reduzem carga em sistemas caros
Exemplo: Redis para cache em memória
3. Índices de Busca
Permitem busca por palavras-chave
Filtram e agregam dados
Exemplo: ElasticSearch para busca full-text
4. Stream Processing
Enviam mensagens entre processos
Processam dados em tempo real
Exemplo: Apache Kafka para streaming
5. Batch Processing
Processam grandes volumes de dados
Executam em background
Exemplo: Spark para análise de dados
Por Que Precisamos Repensar Design?
O Instagram tinha apenas 13 engenheiros quando foi vendido por $1 bilhão. Como uma equipe tão pequena conseguiu escalar para milhões de usuários?
A resposta está em como eles combinaram essas ferramentas especializadas:
Escolha Certa de Ferramentas
Cada ferramenta tem seus trade-offs
Não existe bala de prata
É preciso entender os limites de cada uma
Composição Inteligente
Ferramentas precisam trabalhar juntas
Garantir consistência entre sistemas
Manter complexidade gerenciável
Abstrações Corretas
Esconder complexidade desnecessária
Manter flexibilidade para mudanças
Permitir evolução independente
Os Três Pilares de Sistemas Data-Intensive
Quando projetamos sistemas de dados, três preocupações são fundamentais: confiabilidade, escalabilidade e manutenibilidade. Vamos entender cada uma delas.
1. Confiabilidade: Continuando Funcionando Mesmo Quando Algo Dá Errado
Seus usuários esperam que o sistema:
Funcione como esperado
Tolere erros de uso
Tenha boa performance
Previna acessos não autorizados
Mas falhas acontecem. Vamos ver os tipos mais comuns:
Falhas de Hardware
Discos rígidos falham anualmente em uma taxa de 2-4%
Em um cluster com 10.000 discos, você perde 1 disco por dia!
Solução: redundância de hardware e replicação de dados
A Netflix criou o Chaos Monkey, que propositalmente derruba máquinas em produção. Por quê? Para garantir que o sistema continue funcionando mesmo com falhas.
Falhas de Software
Mais difíceis de prever que hardware
Bugs que afetam todos os servidores ao mesmo tempo
Processos que consomem recursos de maneira incorreta
Dependências que ficam lentas ou param de responder
Por exemplo: no segundo do tempo extra de 2012, muitos sistemas travaram devido a um bug no kernel Linux que não considerava esse cenário.
Falhas Humanas
Maior causa de falhas em produção (70-90%)
Erros de configuração são mais comuns que falhas de hardware
Soluções:
Design que minimiza oportunidades de erro
Ambientes de teste bem projetados
Monitoramento detalhado
Rollbacks rápidos
2. Escalabilidade: Lidando Com Crescimento
Mesmo um sistema confiável hoje pode falhar se a carga aumentar 10x. Como pensamos sobre escalabilidade?
Descrevendo Carga
Precisamos de números concretos. Exemplos de parâmetros:
Requisições por segundo
Proporção de leituras/escritas
Usuários simultâneos
Taxa de cache hit
O Twitter é um ótimo exemplo:
Postar tweet: 4.6k req/s (média), 12k req/s (pico)
Ler timeline: 300k req/s
Eles tinham duas opções para implementar a timeline:
Recuperar tweets na hora da leitura
Manter uma timeline pré-computada
A segunda opção ganhou, mesmo sendo mais complexa na escrita, pois leituras são muito mais comuns que escritas.
Medindo Performance
Métricas importantes:
Latência: tempo esperando para ser processado
Response time: tempo total que o usuário espera
Throughput: número de requisições por segundo
O Amazon descobriu que cada 100ms de atraso custa 1% em vendas. Por isso, olhamos percentis.
Para entender melhor, imagine que seu sistema processa 100 requisições:
p50 (mediana) = 200ms significa que 50 requisições são mais rápidas que isso
p95 = 1s significa que 95 requisições são mais rápidas que 1 segundo
p99 = 2s significa que apenas 1 requisição é mais lenta que 2 segundos
Veja que não falamos da média (average) aqui. Apesar de ela ser um número relevante, não é tanto quanto a mediana.
Você poderia ter um sistema que tem 100 requisições de 100ms, e outras 10 de 500ms. A média seria 136ms, que não é tão alto, mas o p95 é de 500ms! O que quer dizer que 5% dos seus usuários estão com uma performance abaixo do esperado.
Numa escala global, esses 5% se tornam cada vez mais relevantes.
Esses números são críticos: usuários abandonam sites que demoram mais que 3 segundos para carregar.
Tipos de Escalabilidade
Quando enfrentamos problemas de carga, temos duas opções principais:
Scaling Up (Vertical)
Adicionar mais recursos à sua máquina
Exemplo: Aumentar RAM de 8GB para 32GB, ou CPU de 4 para 16 cores
Mais simples mas tem limite físico
Geralmente mais caro
Scaling Out (Horizontal)
Adicionar mais máquinas
Exemplo: De 2 para 10 servidores web
Mais complexo mas sem limite teórico
Normalmente mais barato a longo prazo
Geralmente empresas usam uma combinação das duas abordagens. Como o Instagram: eles começaram com scaling up por simplicidade, mas migraram para scaling out conforme cresceram.
3. Manutenibilidade: Fazendo Sistemas Evoluírem
Estima-se que 40-80% do custo de software está na manutenção. Como facilitamos isso?
Operabilidade
Um sistema com boa operabilidade permite que a equipe de operações:
Monitore saúde do sistema
Identifique problemas rapidamente
Mantenha sistemas atualizados
Automatize processos comuns
Documente conhecimento
Simplicidade
Remova complexidade acidental
Use abstrações corretas
Evite estado compartilhado
Minimize dependências
Por exemplo: o LinkedIn migrou sua arquitetura de mensagens gradualmente, sempre mantendo simplicidade como prioridade.
Evolutividade
Torne mudanças fáceis
Abstrações que permitem mudanças
Processos para evolução contínua
O GitHub é um ótimo exemplo: eles conseguiram migrar sua arquitetura mantendo APIs compatíveis.
Por que System Design Importa
Esses são alguns pensamentos meus do por que esse conteúdo é importante para todo engenheiro de software.
Carreira
Parte crucial de entrevistas senior+
Necessário para liderar projetos
Fundamental para arquitetos
Impacto
Decisões afetam milhares de usuários
Erros podem custar muito caro
Bom design reduz custos a longo prazo
Crescimento
Base para entender sistemas modernos
Ajuda a tomar melhores decisões
Permite resolver problemas maiores
Começando com System Design
Se você está começando agora, foque em:
Entender os fundamentos
Como sistemas distribuídos funcionam
Principais padrões arquiteturais
Trade-offs comuns
Praticar com sistemas reais
Monte um projeto pequeno mas completo
Use diferentes componentes juntos
Monitore e meça performance
Aprender com casos reais
Leia blogs de engenharia de grandes empresas
Estude postmortems de falhas
Participe de discussões técnicas
🌟 Resumo
Sistemas modernos precisam ser:
Confiáveis: continue funcionando com falhas
Escaláveis: mantenha performance com carga
Manuteníveis: permita evolução contínua
Não existe bala de prata: cada decisão é um trade-off
Exemplos práticos como Twitter e Netflix mostram como aplicar esses conceitos
Monitoramento e métricas são essenciais em todos os aspectos
Comece pequeno: foque em entender fundamentos antes de tentar resolver problemas complexos
📚 Próximos Capítulos
Nos próximos artigos desta série, vamos explorar:
Modelos de dados e linguagens de consulta
Armazenamento e recuperação
Codificação e evolução
Essa irá cobrir a Parte 1 do livro: Fundamentos de Sistemas de Dados do DDIA.
Lembrando que o objetivo desse artigo não é substituir o livro. Mas sim tentar mostrar, na minha visão, quais os principais pontos e conteúdos de cada capítulo.
Recomendo a leitura do livro todo para qualquer profissional de engenharia de software e adjacentes. Faça um favor pra você mesmo, e leia. O livro é excelente.
Muito obrigado por ser um assinante ou leitor, e ter chegado até o final! Minha meta para o mês passado era de 700 assinantes, e chegamos a quase 800. 🙌
Se você quiser fazer mais algo pra me ajudar, compartilhe esse artigo com outras pessoas e clique no botão de ❤️ curtir.
Muito massa!
Quanto ao cálculo dos percentis de tempo de resposta, os números foram "chutados" ou existe um padrão de cálculo em eng. de software para descobrir esses percentis?