o problema
Em 2012 o SSD tinha acabado de virar padrão para dados online, e a intuição da comunidade era clara: flash tem número limitado de ciclos de programação e apagamento, logo o recurso a economizar é escrita. Software de banco de dados chegava a amplificar escrita por 100 — uma página inteira de 4 KB, 8 KB ou 16 KB reescrita para mudar menos de 100 bytes. O próprio SSD já amplifica entre 1,1 e 3 vezes por conta própria. Um storage engine que economizasse escrita economizaria hardware.
O segundo problema era de organização. Cada aplicação que precisava guardar dados em disco local acabava construindo o próprio subsistema de armazenamento, e mesmo o caso simples é difícil: checksum contra corrupção de mídia, consistência depois de crash, chamadas de sistema na ordem certa para garantir durabilidade, tratamento correto dos erros que o file system devolve. O RocksDB nasceu do código do LevelDB para ser essa peça comum — uma biblioteca embutida, de um nó só, sem replicação e sem balanceamento, deixando isso para a camada de cima.
a ideia
Este paper não apresenta uma arquitetura. Ele apresenta a lista do que o time achava em 2012 e mediu depois. A conclusão que organiza o texto é que o gargalo se moveu, e a otimização que estava em curso quando ele se moveu virou trabalho com retorno decrescente.
Write amplification saiu de cena primeiro. Os autores pesquisaram 42 implantações de ZippyDB e MyRocks em produção e olharam quatro métricas: endurance do flash, banda de leitura, CPU e espaço. A maioria estava limitada por espaço. Nem os ciclos de escrita nem o IOPS chegavam perto do que o SSD entregava. O alvo virou espaço em disco. Anos depois, com o preço de CPU e memória subindo em relação ao de SSD, a CPU entrou na lista — não porque o SSD ficou rápido demais para o software, hipótese que os autores rejeitam explicitamente, mas porque reduzir consumo de CPU permite configurações de hardware mais baratas.
como funciona
A estrutura é uma LSM-tree. Escrita entra numa MemTable em memória, implementada como skiplist, e no write-ahead log. Quando a MemTable enche, ela e o WAL congelam, um novo par é alocado, e o conteúdo é despejado num arquivo SSTable ordenado, dividido em blocos de tamanho uniforme com um bloco de índice para busca binária. Compaction pega SSTables de um nível que estourou o alvo de tamanho e funde com os que têm faixa de chave sobreposta no nível seguinte, descartando dado morto. Leitura percorre MemTables, depois os SSTables do nível 0, depois os níveis acima; bloom filters evitam abrir arquivo à toa, e scan precisa varrer todos os níveis.
O ajuste fino está no estilo de compaction, e os números do micro-benchmark do paper mostram o tamanho do trade-off. Leveled: write amplification 16,07 e 9,8% de overhead máximo de espaço. Tiered: write amplification cai para 4,8, mas o overhead de espaço vai a 94,4% e o custo de I/O por seek de iterador quase triplica. FIFO, que só descarta arquivos velhos ao bater um limite de tamanho, chega a 2,14 de write amplification e 967 I/Os por seek. A resposta ao problema de espaço foi o dynamic leveled compaction, que dimensiona cada nível a partir do tamanho real do último nível em vez de usar alvos estáticos: overhead estável em 13%, contra picos de 90% no leveled clássico.
o que isso custou
O apêndice C lista três decisões que os autores revisitariam, e a primeira é “customização é sempre boa para o usuário”. A quantidade de knobs que deu tração ao projeto virou reclamação: entre 39 implantações de ZippyDB, mais de 25 configurações distintas, e a configuração ótima depende não do sistema que embute o RocksDB, mas da carga que as aplicações acima dele geram. Quem embarca RocksDB dentro de um produto entregue a terceiros herda um sistema que o cliente não sabe ajustar e o fornecedor não quer ajustar.
Compatibilidade de formato é o outro custo permanente. Deploy incremental e rollback exigem que o dado em disco seja legível tanto por versões antigas quanto por novas, com release mensal — o que significa carregar todos os formatos já escritos e manter testes cruzados entre versões.
Nem toda proteção existe. Dados acima da camada de I/O, na MemTable e no block cache, ainda não eram cobertos por checksum quando o paper foi escrito; checksum por par chave-valor estava em implementação. O WAL não tem checksum de arquivo. E a API de timestamp definido pela aplicação, que rendeu ganho de throughput de 1,2 a 2,0 vezes no DB_bench, é admitidamente mais complicada, sujeita a mau uso, consome mais disco e reduz a portabilidade para outros sistemas.
onde isso aparece hoje
A LSM-tree de 1996 continua sendo a estrutura principal, e os autores dizem que revisitam essa escolha com frequência e sempre chegam ao mesmo lugar. O RocksDB é o motor de armazenamento do MyRocks no MySQL do Facebook, onde substituir o InnoDB reduziu a metade a pegada de espaço do UDB, e aparece no TiDB, no CockroachDB, no MongoDB, no Flink, no Kafka Streams e no EVCache da Netflix. O texto trata a escolha de compaction como caso concreto da conjectura RUM: leitura, atualização e memória, escolha dois.