antonio leandro

dados e armazenamento

Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service

paper · núcleo · Mostafa Elhemali, Niall Gallagher, Nick Gordon, et al. · · ~42 min de leitura do original

a tese

previsibilidade vale mais que eficiência: o dynamodb desacopla o controle de admissão da partição, corta cada otimização que esconde trabalho e aceita gastar mais no caso normal para nunca ter um caso ruim

o que fica

  1. O throttling do DynamoDB antigo não era falha de hardware: a vazão era alocada estaticamente por partição, e dividir uma partição por tamanho dividia a vazão junto, deixando a parte quente com menos capacidade do que tinha antes do split.
  2. Cache que só é consultado quando erra cria comportamento bimodal — o MemDS dispara um refresh assíncrono mesmo quando acerta, para que a frota de metadados receba tráfego constante e um cache frio não vire falha em cascata.
  3. Uma réplica que guarda só o write-ahead log, sem a B-tree, entra no grupo em segundos em vez dos minutos que a cópia completa levaria, e é o que restaura o quórum de durabilidade quando um nó cai.
  4. Antes de disparar uma eleição, o follower pergunta aos outros se eles enxergam o líder; isso derrubou os falsos positivos de detecção de falha causados por gray failure, que sozinhos já custavam disponibilidade.
  5. Verificar continuamente os dados em repouso — comparando as três réplicas entre si e com uma réplica reconstruída dos logs arquivados — é, segundo os autores, o método mais confiável contra corrupção silenciosa e bug de software.
  6. O estado de rollback é diferente do estado inicial, então o DynamoDB testa downgrade antes de todo deploy e faz deploy em duas fases: primeiro todos aprendem a ler a mensagem nova, depois alguém começa a enviá-la.

o problema

O Dynamo original resolveu escala e disponibilidade, mas era single-tenant: cada time da Amazon operava sua própria instalação, virava especialista em partes do banco e carregava a complexidade operacional inteira. Isso acabou virando barreira de adoção. Enquanto isso, S3 e SimpleDB apareciam com a promessa oposta — serviço gerenciado, elástico, sem patch nem cluster para configurar. Os engenheiros preferiam o serviço gerenciado mesmo quando o Dynamo servia melhor ao caso de uso. O SimpleDB, por sua vez, limitava a tabela a 10GB e tinha latência imprevisível de leitura e escrita, porque indexava todos os atributos e atualizava o índice a cada write. O desenvolvedor voltava a quebrar dados entre várias tabelas: um novo fardo operacional para resolver o antigo.

O DynamoDB de 2012 juntou as duas metades, e criou um problema próprio. O cliente declarava vazão em RCUs e WCUs, e o sistema dividia essa vazão igualmente entre as partições. Uma tabela com 3.200 WCUs virava quatro partições de 800 WCUs cada. A conta só fecha se o acesso for uniforme — e não é. Duas patologias apareceram: hot partitions, quando o tráfego se concentra em poucos itens, e throughput dilution, quando um split por tamanho corta a vazão de cada filha pela metade. Nos dois casos o cliente levava throttling com a tabela tendo capacidade de sobra, e a resposta prática era superprovisionar sem usar.

a ideia

Tirar o controle de admissão de dentro da partição. Se a vazão é uma propriedade da tabela, ela deveria ser contada no nível da tabela, não recortada em cotas rígidas por pedaço de key range. A partição passa a poder estourar sempre; quem garante o isolamento é um serviço central de tokens.

O segundo movimento é mais geral e vale além do banco: projetar para previsibilidade em vez de eficiência absoluta. Um cache que absorve 99,75 por cento do tráfego é eficiente, mas esconde o trabalho que existiria sem ele — e no dia em que esfria, a origem recebe de uma vez a carga que nunca foi dimensionada. A escolha do DynamoDB é manter o sistema sempre provisionado para o caso ruim, mesmo pagando por isso no caso normal.

como funciona

A tabela é partida por hash da partition key. Cada partição tem três réplicas em AZs distintas formando um replication group, com Multi-Paxos para eleição de líder e lease para mantê-la. Só o líder serve escrita e leitura forte; o write é confirmado quando um quórum persiste o registro no write-ahead log local. Réplicas de armazenamento guardam o WAL e a B-tree; log replicas guardam só o WAL recente e funcionam como acceptors. Por cima disso ficam dezenas de microserviços — metadata, request routers, storage nodes e o autoadmin, que monitora saúde de partições e substitui réplicas ruins.

O controle global de admissão (GAC) mantém token buckets centrais. Cada request router tem um bucket local com tokens de validade curta e, ao ficar sem, pede mais ao GAC, que estima o consumo global e devolve a fatia do cliente. Os servidores GAC formam um hash ring e mantêm estado efêmero: qualquer um pode ser reiniciado sem consequência. Os buckets por partição continuam existindo como defesa em profundidade, com teto, para que nenhuma aplicação tome o nó inteiro. Junto veio o split for consumption: quando o consumo de uma partição passa de um limiar, ela é dividida no ponto sugerido pela distribuição de chaves observada, não no meio do range.

Os metadados saíram do próprio DynamoDB para o MemDS, um store em memória replicado em toda a frota, com uma estrutura Perkle — híbrido de Patricia tree e Merkle tree — que suporta prefixo, range e as operações floor e ceiling. A integridade vem de checksums em cada entrada de log, mensagem e arquivo, dos logs arquivados no S3 com manifesto verificado, e do scrub, que compara réplica viva com réplica reconstruída do histórico de logs. O protocolo de replicação é especificado em TLA+ e verificado por model checking a cada feature nova.

o que isso custou

O split for consumption não salva todo mundo: partição com um único item quente, ou com key range acessado sequencialmente, não se beneficia — o sistema detecta e nem tenta. O on-demand absorve instantaneamente até o dobro do pico anterior; acima disso, a capacidade vai sendo alocada conforme o tráfego sobe. A log replica restaura o quórum de durabilidade, não a capacidade de leitura: ela não tem dados. E toda troca de liderança tem um custo fixo — o novo líder espera o lease do antigo expirar antes de aceitar escrita ou leitura forte.

O MemDS troca eficiência por estabilidade de forma explícita: a carga na frota de metadados é maior do que seria com cache convencional, por construção. Os próprios números do artigo têm limite: os benchmarks YCSB rodados são A e B com distribuição uniforme de chaves e itens de 900 bytes — justamente o caso que o resto do artigo passa trinta páginas dizendo que não acontece na prática.

onde isso aparece hoje

O nome veio do Dynamo, a arquitetura não: o sistema de 2012 em diante é multi-tenant, gerenciado e com quórum liderado por Paxos, não com o modelo descentralizado do antecessor. O artigo relata Lambda, Lake Formation e SageMaker construídos sobre ele, e um Prime Day de 66 horas em 2021 com pico de 89,2 milhões de requisições por segundo. As transações ACID mencionadas de passagem aqui ganharam artigo próprio no ano seguinte, em Distributed Transactions at Scale in Amazon DynamoDB.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·