Design clássico · Staff
Armazenamento de objetos (estilo S3)
Projeto de entrevista clássico. Pontos centrais: storage engines (LSM) e entrega de blobs e vídeo.
Resposta curta
Projeto de entrevista clássico. Pontos centrais: storage engines (LSM) e entrega de blobs e vídeo. Armazenamento de objetos é um serviço de chave e valor para dados grandes: você escolhe uma chave única ao guardar o dado e usa a mesma chave para recuperá-lo.
01 · CONTEXTO E REQUISITOS
O que um armazenamento de objetos promete
Armazenamento de objetos é um serviço de chave e valor para dados grandes: você escolhe uma chave única ao guardar o dado e usa a mesma chave para recuperá-lo. A AWS descreve o S3 como um repositório simples baseado em chaves e diz que ele foi desenhado para atualizar o objeto inteiro, ao contrário de um sistema de arquivos, que aceita atualização parcial e anexação. Este caso é um bom ponto de partida para o levantamento de requisitos de um sistema de armazenamento.
Não existe diretório de verdade. As chaves podem ser qualquer string e podem imitar uma hierarquia, mas renomear um prefixo exige renomear cada objeto que o contém. Por isso, o desenho trata a chave como um nome plano e evita operações que dependam de uma árvore.
Há limites práticos de tamanho: um objeto vai de zero byte a 50 TB, e o maior objeto aceito em um único PUT é de 5 GB. A AWS recomenda upload em partes para objetos a partir de 100 MB, assunto de uma seção adiante.
Os requisitos não funcionais que mandam no desenho são durabilidade e disponibilidade. Para a classe padrão, a AWS declara o projeto para 99,999999999% de durabilidade e 99,99% de disponibilidade de objetos ao longo de um ano. São metas de projeto, não garantias contratuais.
02 · VISÃO GERAL
Quatro blocos e uma separação central
Em linhas gerais, a AWS descreve o S3 como uma API REST sobre HTTP com quatro blocos: uma frota de frontend com a API, um serviço de namespace, uma frota de armazenamento cheia de discos rígidos e uma frota de operações em segundo plano, que a AWS chama de serviços de dados, como replicação e tiering. Cada bloco, por dentro, é feito de muitos serviços: no total são centenas de microsserviços.
No desenho deste estudo, a decisão que mais importa é separar metadados de dados. O namespace guarda a chave e a informação de onde o objeto está; a frota de armazenamento guarda os bytes. Cada lado escala e se protege com a técnica adequada: o namespace precisa de consulta rápida por chave, e o armazenamento precisa de muita capacidade com redundância barata.
O cliente envia um PUT com a chave e os bytes para a API REST do frontend.
O frontend entrega os bytes à frota de armazenamento, que escolhe em quais discos eles ficam.
Só depois que os bytes estão seguros, o frontend registra a chave e o local dos dados no namespace. É uma escolha deste desenho: o objeto só fica visível quando existe no namespace.
Num GET, o frontend consulta o namespace pela chave, descobre onde estão os dados e lê os bytes da frota de armazenamento.
Fora do caminho do cliente, os serviços de fundo cuidam de replicação, tiering e reparo.
03 · DURABILIDADE
Replicação, erasure coding e zonas
As classes padrão guardam cada objeto em vários dispositivos, em no mínimo três zonas de disponibilidade de uma região, e foram projetadas para sustentar os dados mesmo com a perda de uma zona inteira. Esse é o raciocínio de recuperação de desastres aplicado dentro de uma região.
Há duas formas de redundância. Replicação mantém cópias em discos diferentes: protege contra a falha de um disco, permite ler de qualquer cópia, mas em capacidade é cara. Erasure coding divide o objeto em k fragmentos e gera m fragmentos de paridade; enquanto k dos k+m fragmentos estiverem disponíveis, o objeto pode ser lido, e a sobrecarga de capacidade cai para o mesmo número de falhas suportadas.
| Critério | Replicação | Erasure coding |
|---|---|---|
| Como protege | Várias cópias completas em discos diferentes | Fragmentos de dados e de paridade; o objeto se reconstrói com k dos k+m fragmentos |
| Capacidade | Cara: cada cópia ocupa o objeto inteiro | Sobrecarga menor para sobreviver ao mesmo número de falhas |
| Leitura | Pode ler de qualquer cópia | Precisa de k fragmentos disponíveis |
O frontend codifica o objeto em fragmentos e os distribui pelas três zonas.
O namespace registra onde cada fragmento ficou.
A zona B inteira fica indisponível, e com ela os fragmentos que guardava.
Uma leitura continua possível: o frontend busca fragmentos nas zonas que restam, desde que haja fragmentos suficientes para reconstruir o objeto.
Em segundo plano, o serviço de reparo detecta a redundância perdida e recria os fragmentos em discos saudáveis.
Redundância sozinha não basta. Os serviços de armazenamento detectam e reparam rapidamente a redundância perdida e verificam a integridade dos dados com checksums de forma regular.
04 · DESEMPENHO E CALOR
Discos grandes, E/S limitada e pontos quentes
Discos rígidos ganharam muita capacidade, mas o acesso aleatório continua mecânico. A AWS cita cerca de 120 operações por segundo em acesso aleatório contínuo, valor parecido com o de 2006, quando o S3 foi lançado. A capacidade cresce e o desempenho de acesso aleatório fica estagnado, e essa tensão influencia o desenho do serviço.
O problema decorrente é balancear a demanda de E/S entre um número enorme de discos, que a equipe do S3 chama de gestão de calor. Se muitos pedidos caem sobre poucos discos, formam-se pontos quentes: nada cai, mas os pedidos enfileiram, e pontos quentes em discos individuais criam latência de cauda.
A resposta combina redundância e espalhamento. A redundância espalha a carga e permite desviar o tráfego de pontos quentes. Além disso, mesmo que um objeto seja codificado em dezenas de discos, objetos diferentes vão para conjuntos de discos diferentes, de modo que os acessos de cada cliente se espalham por muitos discos.
Isso traz dois benefícios: os dados de um cliente ocupam pouco de cada disco, o que dá isolamento de carga, e uma carga individual pode estourar para uma escala de discos que seria difícil e cara de construir como sistema isolado.
Do lado do cliente, a regra é semelhante ao particionamento de dados: a AWS documenta ao menos 3.500 gravações ou 5.500 leituras por segundo por prefixo particionado, sem limite para o número de prefixos em um bucket. O escalonamento é gradual, não instantâneo; para aumentar a vazão, distribua as chaves em vários prefixos.
05 · OBJETOS GRANDES
Upload em partes
Um upload em partes envia um único objeto como um conjunto de partes independentes. As partes podem seguir em paralelo para melhorar a vazão, e, se a transmissão de uma delas falha, só ela é retransmitida, sem afetar as outras.
O fluxo tem três passos: iniciar, enviar partes e concluir. Cada parte tem um número entre 1 e 10.000 e devolve um ETag, e o cliente deve registrar os dois. Ao concluir, o serviço cria o objeto concatenando as partes em ordem crescente do número da parte.
O cliente inicia o upload e recebe um identificador único. Neste desenho, o serviço cria o registro do upload nos metadados.
O cliente envia as partes em paralelo, cada uma com seu número, e guarda o ETag devolvido por cada uma.
Uma parte falha no caminho. O cliente reenvia só essa parte, sem recomeçar o objeto.
O cliente conclui o upload com a lista de números e ETags. O serviço monta o objeto em ordem de número e só então ele passa a existir como um objeto único.
As partes enviadas e não concluídas continuam ocupando espaço e gerando cobrança até que o upload seja concluído ou interrompido.
06 · CONSISTÊNCIA E VERSÕES
Ler o que acabou de gravar e não perder o passado
O S3 começou com consistência eventual. Sem consistência forte, as aplicações precisavam de código extra ou de bancos de dados para manter os objetos consistentes. A AWS passou a entregar consistência forte de leitura após escrita: depois de uma gravação, sobrescrita ou exclusão bem-sucedida, qualquer leitura seguinte recebe a versão mais recente, e a listagem também reflete a mudança.
Em um desenho próprio, isso se reflete na ordem de gravação mostrada na visão geral: os bytes ficam seguros primeiro e a chave só é registrada no namespace depois. Assim, uma leitura que encontra a chave sempre encontra os dados.
O versionamento complementa a proteção. Ele vem desativado por padrão e precisa ser habilitado. Com ele ativo, apagar um objeto insere um marcador de exclusão em vez de remover o objeto, e sobrescrever cria uma nova versão, de modo que a anterior pode ser restaurada.
Perguntas frequentes
O que é Armazenamento de objetos (estilo S3)?
Projeto de entrevista clássico. Pontos centrais: storage engines (LSM) e entrega de blobs e vídeo.
O que o design de Armazenamento de objetos (estilo S3) cobre?
Ele está organizado nestas seções: O que um armazenamento de objetos promete, Quatro blocos e uma separação central, Replicação, erasure coding e zonas, Discos grandes, E/S limitada e pontos quentes, Upload em partes e Ler o que acabou de gravar e não perder o passado.
Quanto tempo leva Armazenamento de objetos (estilo S3) e qual é o nível?
Leva cerca de 17 minutos para ler e tem nível Staff.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.