Pular para o conteúdo principal

LSM Trees e Log-Structured Storage: A Arquitetura por Trás dos Bancos de Dados Modernos

Publicado em 21 de dezembro de 202528 min de leitura
Imagem de tecnologia relacionada ao artigo log-structured-storage-lsm-trees

LSM Trees e Log-Structured Storage: A Arquitetura por Trás dos Bancos de Dados Modernos

Como o Discord guarda trilhões de mensagens ou bancos de dados modernos processam milhões de cliques por segundo sem travar? O segredo não está nas tabelas tradicionais, mas nas LSM Trees. Ao inverter a lógica clássica e transformar cada escrita em um fluxo contínuo de dados, essa arquitetura venceu a lentidão física do disco e se tornou a base da infraestrutura de alta performance.

Se você quer entender como bancos de dados como Cassandra e RocksDB alcançam velocidades absurdas, precisa conhecer o poder do Log-Structured Storage. Vamos mergulhar na ciência que permite transformar o caos das escritas aleatórias em uma linha reta de performance pura.

1. O Problema com B-Trees para Escritas Intensivas

1.1 Como B-Trees Funcionam

B-Trees mantêm dados ordenados para buscas eficientes. Cada nó contém múltiplas chaves ordenadas e ponteiros para filhos. Buscas são logarítmicas — você navega da raiz até a folha, comparando chaves em cada nível. Updates localizam a folha relevante e modificam o valor in-place. Para bancos de dados relacionais com cargas equilibradas de leitura e escrita, B-Trees são excelentes.

O problema aparece com escritas intensivas. Cada update requer ler a página da folha do disco, modificá-la em memória, e escrever de volta. Como os dados estão ordenados e espalhados pelo disco, essas operações são I/O aleatório. Discos mecânicos (HDDs) podem fazer apenas ~100-200 operações aleatórias por segundo. Mesmo SSDs, embora muito mais rápidos, têm custos significativos para writes aleatórios e sofrem degradação com write amplification. Para cenários com milhões de escritas por segundo, B-Trees não escalam.

1.2 A Insight do Log-Structured Storage

A observação fundamental do log-structured storage é que escrita sequencial é muito mais rápida que escrita aleatória. Em vez de atualizar dados in-place, você simplesmente adiciona ao final de um arquivo (como um log). Isso converte todas as escritas em sequenciais, alcançando throughput limitado apenas pela largura de banda do disco, não pela latência de seeks aleatórios. Um HDD moderno pode escrever sequencialmente a 100-200 MB/s; fazer updates aleatórios de 4KB páginas seria centenas de vezes mais lento.

2. Arquitetura de LSM Trees

2.1 Componentes Principais

Uma LSM Tree consiste em múltiplas camadas. A primeira é um buffer em memória, chamado MemTable (ou write-ahead buffer), onde escritas são inicialmente inseridas. Quando o MemTable enche, ele é convertido em um arquivo ordenado imutável no disco, chamado SSTable (Sorted String Table). Ao longo do tempo, múltiplos SSTables se acumulam em disco. Periodicamente, SSTables são mesclados (merged) em arquivos maiores através de um processo chamado compaction.

Cada escrita vai primeiro para o MemTable, que é uma estrutura ordenada em memória (tipicamente uma skip list ou árvore balanceada). Como está em memória, a escrita é extremamente rápida — limitada apenas pela CPU, não por I/O. Para durabilidade, um Write-Ahead Log (WAL) registra cada operação antes de ir ao MemTable; se o servidor crashar, o WAL permite reconstruir o MemTable não persistido.

2.2 SSTables e Imutabilidade

Quando o MemTable atinge um determinado tamanho (configurável), ele é "flushed" (descarregado) para o disco como um arquivo SSTable (Sorted String Table). A característica crucial dessa abordagem é que SSTables são estritamente imutáveis: uma vez escritos no disco, eles nunca são modificados, substituídos ou atualizados no local. Quando ocorrem atualizações ou exclusões de dados, o sistema não modifica os SSTables existentes; em vez disso, novas versões dos registros ou marcadores especiais chamados "tombstones" (lápides) são escritos em SSTables mais recentes. Durante as operações de leitura, o sistema verifica os SSTables mais recentes primeiro, garantindo que versões mais recentes dos dados tenham precedência sobre versões antigas.

Essa imutabilidade é a pedra angular da eficiência e simplicidade das LSM Trees. Ela simplifica drasticamente a concorrência — não há necessidade de locks complexos para operações de leitura, pois os dados nunca mudam uma vez que estão em um SSTable. Isso também simplifica significativamente operações de backup e replicação: copiar arquivos imutáveis é uma operação trivial e segura, sem risco de leituras inconsistentes durante a cópia. Além disso, a imutabilidade permite compressão de dados extremamente eficiente, já que você pode comprimir SSTables inteiros de uma só vez sem se preocupar com atualizações parciais ou consistência durante a compressão. A previsibilidade dos arquivos imutáveis também facilita o cache de blocos e otimizações de I/O.

2.3 Compaction: Mesclando SSTables

Com o tempo, SSTables se acumulam. Isso tem dois custos: espaço desperdiçado por valores obsoletos (substituídos por versões mais recentes), e leituras mais lentas (que precisam consultar múltiplos SSTables para encontrar a versão mais recente). Compaction resolve ambos: mescla SSTables, descartando valores obsoletos e produzindo arquivos maiores e mais consolidados.

Existem três estratégias principais:

  1. Size-Tiered Compaction (STCS): Usada quando a performance de escrita é a prioridade máxima (ex: Cassandra). Mescla arquivos de tamanho similar. Gera menos Write Amplification, mas causa fragmentação de chaves entre arquivos, o que prejudica leituras.
  2. Leveled Compaction (LCS): Usada quando a performance de leitura é crítica (ex: RocksDB, LevelDB). Organiza dados em níveis (L0, L1, L2...). No L1 em diante, não há sobreposição de chaves entre arquivos. Isso garante que buscas verifiquem no máximo um arquivo por nível.
  3. Universal Compaction: Uma estratégia híbrida que tenta equilibrar as duas abordagens, comum em bancos de dados que variam muito sua carga de trabalho.

Explorador de Arquitetura LSM

Visualize o fluxo de dados do MemTable até o disco

RAM: MemTable
Vazio - Aguardando escritas...
Disk: Level 0 (SSTables)
Nenhum SSTable no disco
Disk: Level 1 (Sorted & Consolidated)
Aguardando compactação...
Fluxo de Eventos

2.4 Bloom Filters: A Ciência da Probabilidade

Para evitar que cada leitura tenha que abrir todos os arquivos SSTable do disco, as LSM Trees usam Bloom Filters. Um Bloom Filter é uma estrutura de dados probabilística que responde: "esta chave está neste arquivo?".

  • Se responder Não: A chave definitivamente não está lá. Pulamos o arquivo.
  • Se responder Sim: A chave talvez esteja lá. Precisamos verificar o arquivo.

A eficiência de um Bloom Filter depende do número de hash functions (k) e do número de bits por chave (m/n). No RocksDB, o padrão é 10 bits por chave, o que garante uma taxa de falso positivo de apenas 1%. Isso significa que 99% das vezes verificamos apenas o arquivo que realmente contém o dado.

3. Trade-offs de LSM Trees

3.1 Escritas Rápidas, Leituras Mais Complexas

O principal trade-off de LSM Trees é que escritas são otimizadas às custas de leituras. Uma leitura potencialmente precisa verificar o MemTable mais todos os SSTables até encontrar a versão mais recente da chave. Para mitigar isso, LSM Trees usam Bloom Filters — estruturas probabilísticas que rapidamente indicam se uma chave definitivamente não está em um SSTable, evitando leituras desnecessárias. Com Bloom Filters bem dimensionados, a maioria das leituras verifica apenas 1-2 SSTables.

3.2 Write Amplification

Compaction gera write amplification: cada byte de dados pode ser reescrito múltiplas vezes conforme é movido para níveis mais altos. Em leveled compaction típica, write amplification é 10x ou mais — cada byte escrito pelo usuário gera 10+ bytes de I/O real. Isso aumenta desgaste de SSDs e limita throughput sustentável. Tunar estratégias de compaction para equilibrar read/write performance e write amplification é uma arte que depende da carga de trabalho específica.

3.3 Space Amplification

Como deletes e updates não removem imediatamente valores antigos, há space amplification temporária — o banco ocupa mais espaço do que os dados "vivos" justificariam. Isso é resolvido por compaction, mas durante picos de escrita, pode haver necessidade de provisionar espaço extra em disco.

4. LSM Trees vs B-Trees vs Bw-Trees

Para escolher o motor de storage correto, você deve entender as diferenças fundamentais:

| Característica | B-Trees | LSM Trees | Bw-Trees (Latch-free) | | :--- | :--- | :--- | :--- | | Performance Escrita | Média (I/O Aleatório) | Altíssima (Sequencial) | Alta (Compare-and-swap) | | Performance Leitura | Altíssima | Média (Exige Merge) | Alta | | Write Amplification | Alta | Média/Alta | Baixa | | Concorrência | Travas (Locks) | Alta (Imutável) | Altíssima (Wait-free) | | Ideal para... | Queries complexas, SQL | Big Data, Logs, Ingestão | Sistemas In-Memory |

As Bw-Trees, popularizadas pelo Microsoft Hekaton, tentam eliminar o gargalo de travas em sistemas multi-core usando estruturas de dados sem lock e técnicas de append-only similares às LSM, mas mantendo a estrutura de árvore para buscas rápidas.

5. Aplicações Práticas

5.1 RocksDB e LevelDB

LevelDB, desenvolvido pelo Google, foi uma das primeiras implementações amplamente usadas de LSM Trees. RocksDB, fork do Facebook, extendeu LevelDB com features para produção: compaction configurável, column families, transactions, e muito mais. RocksDB é agora o storage engine embutido mais popular, usado por MySQL (MyRocks), CockroachDB, TiKV, e dezenas de outros sistemas.

4.2 Apache Cassandra

Cassandra usa LSM Trees para cada tabela. Escritas vão para MemTables por partição, flushed para SSTables, e compactados periodicamente. A eficiência de escrita de LSM Trees é parte do que permite Cassandra escalar linearmente para milhares de nós e bilhões de linhas.

4.3 Time-Series Databases

Bancos de dados de séries temporais como InfluxDB e TimescaleDB usam variações de LSM Trees otimizadas para dados ordenados por tempo. Como dados de séries temporais são naturalmente append-only e raramente atualizados, as características de LSM Trees são particularmente vantajosas.

6. Column Families: Organizando dados no RocksDB

Uma funcionalidade avançada do RocksDB é o uso de Column Families. Elas permitem que você divida o seu banco de dados em seções lógicas independentes que compartilham o mesmo WAL, mas têm seus próprios MemTables e conjuntos de arquivos SSTable.

Por que usar Column Families?

  • Configurações Diferentes: Você pode ter um Column Family para "Logs" (usando Size-Tiered Compaction) e outro para "User Profiles" (usando Leveled Compaction) no mesmo banco de dados físico.
  • Deleção Atômica: Você pode apagar um Column Family inteiro instantaneamente, sem ter que escrever Tombstones para cada chave.
  • Isolamento de Cache: Evita que uma carga pesada de leitura em "Logs" expulse os dados quentes de "User Profiles" do Block Cache.

7. ClickHouse e a Fusão de Partes (OLAP)

O ClickHouse, um dos bancos de dados analíticos mais rápidos do mundo, utiliza um motor chamado MergeTree. Embora focado em analytics (OLAP), o MergeTree é fundamentalmente um design baseado em LSM:

  1. Dados são inseridos em pequenos "parts" (arquivos ordenados).
  2. O sistema faz o "merge" desses parts em background.
  3. Diferente do RocksDB, o ClickHouse foca em colunas imutáveis, permitindo compressões absurdas (muitas vezes de 10x ou 20x).

8. LSM Trees no Contexto de Blockchain

Blockchains como o Ethereum e o Solana enfrentam o desafio do "State Bloat" (crescimento infinito do estado). A maioria dos nós de rede usa o RocksDB para armazenar o estado global da rede. A imutabilidade das SSTables é uma aliada perfeita para o modelo de "Merkle Trees" das blockchains, onde cada alteração gera um novo hash. O desafio aqui é gerenciar o Write Amplification causado pelas milhares de transações por segundo, o que exige SSDs de nível enterprise para suportar a carga de compaction constante.

9. Física do Storage: O Gap de Latência

Para entender a necessidade das LSM Trees, veja a diferença de latência em ordens de magnitude:

| Memória | Latência (ns) | Referência de Tempo Humana | | :--- | :--- | :--- | | L1 Cache | 0.5 ns | 1 batida de coração | | L2 Cache | 7 ns | 14 batidas | | RAM | 100 ns | 3 minutos | | SSD NVMe (Acesso Aleatório) | 10.000 ns | 5 horas | | HDD (Acesso Aleatório) | 10.000.000 ns | 6 meses |

As LSM Trees tentam mover as operações do nível de "6 meses" (seeks aleatórios no HDD) ou "5 horas" (aleatório no SSD) para o nível de escrita sequencial, que é ordens de magnitude mais eficiente na prática.

10. O Futuro: Learned Indexes e IA

A pesquisa em bancos de dados está caminhando para os Learned Indexes. A ideia é substituir as estruturas de dados tradicionais (como o índice do SSTable) por pequenos modelos de Machine Learning (redes neurais simples ou regressões lineares) que "aprendem" onde os dados estão localizados no disco. Isso poderia reduzir o tamanho do índice no RocksDB em 90%, deixando mais RAM livre para o cache de dados e acelerando as buscas p99.

11. Otimizando o RocksDB: Padrões de Produção

Se você for implementar o RocksDB em um sistema de alta carga, precisa domar suas dezenas de opções de tuning. Aqui estão as três configurações mais críticas:

  1. Block Cache: Define quanta memória RAM será usada para cachear blocos de dados lidos dos SSTables. Diferente do Page Cache do SO, o Block Cache do RocksDB entende os dados e evita cópias desnecessárias.
  2. MemTable Size: Se for muito pequeno, você gera muitos arquivos SSTable pequenos (churn alto). Se for muito grande, o tempo de recuperação (recovery) após um crash aumenta, pois o WAL será gigante.
  3. Filter Policy: Aumentar os bits por chave no Bloom Filter (ex: de 10 para 15) pode reduzir drasticamente o I/O de leitura ao custo de um pouco mais de memória RAM.

12. LSM Trees e o Hardware Moderno: NVMe e Optane

A arquitetura LSM Tree foi concebida quando discos mecânicos eram o padrão. Com a chegada dos SSDs NVMe e memórias persistentes (NVM), a latência de busca aleatória caiu drasticamente.

No entanto, as LSM Trees continuam relevantes porque:

  • Write Endurance: SSDs têm um limite de escritas. O padrão sequencial das LSM Trees é muito mais "gentil" com o hardware do que os updates in-place das B-Trees.
  • Computational Storage: Novos SSDs "inteligentes" permitem que o processo de Compaction ocorra dentro do próprio controlador do disco, liberando a CPU principal do servidor para tarefas de lógica de negócio.

12.1 ScyllaDB e o Modelo Shard-per-Core

O ScyllaDB é uma reimaginação do Cassandra em C++ que utiliza LSM Trees com uma arquitetura de "Shared-nothing". Nele, cada core da CPU gerencia seu próprio conjunto de LSM Trees (Shards).

  • Sem Locks: Como cada core é dono de sua partição, não há contenção de CPU.
  • Direct I/O: O ScyllaDB pula o Page Cache do Linux e fala diretamente com o SSD.
  • Unified Scheduler: O sistema decide dinamicamente quanta CPU dar para as escritas dos usuários vs. para o background compaction.

13. LSM Trees no Cloud-Native: O Modelo S3

Empresas como Snowflake e ClickHouse Cloud levaram o conceito de SSTables para o armazenamento de objetos (AWS S3, Google Cloud Storage). Nesse modelo:

  1. As escritas rápidas ocorrem em discos locais (SSDs).
  2. Os SSTables são "flushed" diretamente para o S3.
  3. Como o S3 é imutável por natureza, ele se integra perfeitamente ao design imutável das SSTables.
  4. O Compaction ocorre em instâncias separadas (Stateless Workers), permitindo escalar o processamento de forma independente do armazenamento.

14. Segurança: Criptografia e Deleção Física

A imutabilidade das LSM Trees traz um desafio para a segurança: como apagar dados permanentemente por motivos de conformidade (como a LGPD/GDPR)? Simplesmente escrever um Tombstone não apaga o dado físico do disco imediatamente; ele apenas o "esconde". O dado só desaparece de fato quando o processo de Compaction mescla aquele arquivo e decide não incluir a versão antiga no novo arquivo consolidado.

Para garantir a Deleção Física, sistemas modernos permitem forçar um "Manual Compaction" em faixas de chaves específicas ou usam criptografia por chave de usuário (onde apagar a chave torna os dados no disco ilegíveis instantaneamente).

15. Análise Matemática: Por que LCS é melhor para Leitura?

Em uma Size-Tiered Compaction (STCS), uma chave pode existir em qualquer arquivo de qualquer nível. Se você tiver 100 arquivos, a leitura pode ter que verificar 100 Bloom Filters.

Já na Leveled Compaction (LCS), o banco garante que cada nível seja um único intervalo de chaves ordenado.

  • Nível 0: É o único que pode ter sobreposição (pois vem direto do MemTable).
  • Nível 1 em diante: Uma chave existe em apenas um arquivo por nível. Se você tem 7 níveis (típico do RocksDB), sua leitura verificará no máximo 1 (MemTable) + L0_files + 6 arquivos. Isso limita drasticamente a latência de busca no pior caso (p99 latency).

15.1 As Fórmulas da Amplificação

Para o engenheiro de performance, o comportamento da LSM Tree pode ser modelado:

  • Write Amplification (WA): $WA \approx (L \cdot T) / (T - 1)$, onde $L$ é o número de níveis e $T$ é o fator de escala (tipicamente 10).
  • Read Amplification (RA): $RA \approx L$ (em Leveled Compaction com Bloom Filters perfeitos).
  • Space Amplification (SA): $SA \approx (T + 1) / (T - 1)$.

Essas fórmulas mostram que ao aumentar o fator $T$, você melhora a utilização de espaço mas piora drasticamente a performance de escrita.

16. Métricas que um DBA/SRE deve Monitorar

Você não pode operar uma LSM Tree "no escuro". Monitore:

  1. Compaction Pending Bytes: Quantos dados estão esperando para serem compactados. Se este número subir sem parar, sua taxa de escrita está maior que sua capacidade de disco/CPU.
  2. Read Amplification: Média de arquivos consultados por leitura. O ideal é perto de 1.
  3. Level 0 File Count: Se houver muitos arquivos no L0, a escrita pode ser travada (Write Stalls) para permitir que o compaction os limpe.
  4. Block Cache Hit Rate: Indica se sua RAM está bem dimensionada para a carga de leitura.
  • Footer: Um bloco fixo no final do arquivo que contém ponteiros para o índice e para os filtros.

17.1 Pseudo-algoritmo de Flush (MemTable p/ SSTable)

Para os desenvolvedores, o processo de "congelar" a memória e transformá-la em disco segue esta lógica:

python
def flush_memtable(memtable):
    # 1. Transformar em imutável para não bloquear novas escritas
    immutable_memtable = memtable.freeze()
    
    # 2. Criar novo iterador ordenado (geralmente via SkipList)
    iterator = immutable_memtable.get_sorted_iterator()
    
    # 3. Criar novo arquivo SSTable no disco
    sstable_builder = SSTableBuilder(new_file_path())
    
    # 4. Iterar e gravar em blocos
    while iterator.has_next():
        key, value = iterator.next()
        sstable_builder.add(key, value)
        
        # Gerar Bloom Filter em tempo real
        bloom_filter.add(key)
        
    # 5. Gravar metadados e fechar arquivo
    sstable_builder.finish(bloom_filter)
    
    # 6. Remover do WAL (os dados agora estão seguros no disco)
    wal.discard_segments_for(immutable_memtable)

18. Estudo de Caso: Discord e a Jornada do Bilhão

O Discord migrou de Cassandra (em Java) para ScyllaDB (em C++) para gerenciar seu trilhão de mensagens. O motivo principal? Tail Latency (p999) causada pelo Garbage Collection no Java e a ineficiência das LSM Trees originais em determinadas cargas de trabalho.

Com o ScyllaDB, eles aproveitaram o modelo de Shard-per-core, onde as LSM Trees são tão otimizadas que conseguem ler dados do disco quase na mesma velocidade que a rede consegue transmiti-los, mantendo latências abaixo de 10ms mesmo durante picos massivos de tráfego.

19. Quando NÃO usar LSM Trees? (Framework de Decisão)

Apesar de poderosas, elas não são a solução para tudo. Use B-Trees (como o InnoDB do MySQL ou PostgreSQL) se:

  1. Sua carga é 99% leitura: B-Trees têm latência de leitura mais previsível e estável.
  2. Você depende de Range Scans massivos: B-Trees mantêm a ordem física de forma mais rígida, o que pode acelerar buscas como BETWEEN 100 AND 1000000.
  3. Seu dataset é pequeno: O overhead de gerenciar MemTables e Compactions não compensa se os seus dados cabem confortavelmente em RAM.

Use LSM Trees se:

  1. Você tem alta ingestão de dados: Logs, telemetria, feeds de redes sociais.
  2. Você usa Hardware Flash (SSDs): E quer maximizar a vida útil do hardware reduzindo escritas aleatórias.
  3. Você precisa de compressão agressiva: A imutabilidade facilita algoritmos como Zstandard ou LZ4.

20. Conclusão

As LSM Trees mudaram o jogo ao inverter a lógica clássica: em vez de otimizar para leituras (como fariam as B-Trees), elas priorizam a escrita, transformando o lento I/O aleatório em um fluxo sequencial veloz. Essa abordagem é o que permite que sistemas modernos lidem com volumes massivos de dados em tempo real, desde o monitoramento de servidores até o processamento de pagamentos globais.

Dominar esse conceito é essencial para quem projeta sistemas de alta escala. Afinal, entender os trade-offs entre leitura e escrita — e saber como o compaction influencia a sua aplicação — é o que separa um código funcional de um sistema verdadeiramente resiliente e performático.


  • Admission Control: Decidir se uma requisição deve ser admitida no sistema.
  • Anycast: Técnica de roteamento onde o tráfego vai para o nó mais próximo (desafio para limites globais).
  • Block Cache: Cache em RAM para blocos de dados lidos de arquivos de disco.
  • Bloom Filter: Estrutura probabilística que testa se um elemento definitivamente não está em um conjunto.
  • Byte-Addressability: Capacidade de endereçar cada byte individualmente (característica da RAM e PMem).
  • Checkpoint: Captura de um estado consistente do banco de dados no disco.
  • Column Family: Divisão lógica de dados dentro de um mesmo banco de dados LSM.
  • Compaction: Processo de mesclar SSTables, removendo dados obsoletos e otimizando a leitura.
  • Computational Storage: Tecnologia que move o processamento para dentro do dispositivo de armazenamento.
  • Data Locality: Manter dados que são acessados juntos fisicamente próximos no disco.
  • Delta Encoding: Armazenar apenas a diferença entre registros consecutivos para economizar espaço.
  • Direct I/O: Operações de I/O que pulam o cache do sistema operacional.
  • Flush: Ato de escrever o conteúdo do MemTable para um arquivo SSTable no disco.
  • Fractal Tree: Estrutura de dados que combina buffers com B-Trees tradicionais.
  • Index Block: Parte do SSTable que armazena a localização das chaves no disco.
  • IngestSSTable: Técnica de inserir dados já ordenados diretamente no banco de dados.
  • Key Manager: Sistema que gerencia as chaves de criptografia para dados em repouso.
  • L0 (Level 0): O nível mais baixo da LSM Tree, onde arquivos podem ter chaves sobrepostas.
  • Leveled Compaction: Estratégia que organiza SSTables em níveis sem sobreposição de chaves.
  • LSM Tree (Log-Structured Merge Tree): Arquitetura que otimiza escritas convertendo I/O aleatório em sequencial.
  • MemTable: Estrutura de memória (árvore ou skip-list) que recebe as escritas iniciais.
  • Merge Operator: Função customizada que combina múltiplos valores para uma mesma chave durante o compaction.
  • NVM (Non-Volatile Memory): Memória de alta velocidade que mantém dados sem energia.
  • NVMe: Protocolo de transporte para SSDs de alta performance via barramento PCIe.
  • Page Cache: Cache do sistema operacional para arquivos de disco.
  • Partitioned Index: Dividir o índice do SSTable em partes menores para caber no cache.
  • PMem (Persistent Memory): Memória semicondutora persistente de baixa latência.
  • Prefix Bloom Filter: Filtro de Bloom otimizado para buscas por prefixo de chave.
  • Range Scan: Operação de buscar todas as chaves dentro de um intervalo (ex: de A a Z).
  • Read Amplification: O número de leituras de disco necessárias para satisfazer uma única consulta lógica.
  • RocksDB: Storage engine de alta performance de código aberto baseado em LSM Trees.
  • Shard-per-core: Arquitetura onde cada núcleo da CPU tem seus próprios recursos e dados isolados.
  • Size-Tiered Compaction: Estratégia que mescla arquivos de tamanho similar, priorizando escrita.
  • Skip List: Estrutura de dados probabilística usada frequentemente para implementar MemTables.
  • Sorted String Table (SSTable): Formato de arquivo onde chaves e valores são armazenados de forma ordenada e imutável.
  • Space Amplification: A proporção de espaço em disco usado em relação ao tamanho real dos dados "vivos".
  • Tombstone: Registro especial que indica que uma chave foi deletada.
  • Universal Compaction: Algoritmo de compaction flexível que se adapta a diferentes cargas de trabalho.
  • Virtualization of Storage: Separar o armazenamento físico da lógica de acesso aos dados (comum em Cloud).
  • WAL (Write-Ahead Log): Arquivo de log sequencial que garante durabilidade de dados ainda não persistidos no SSTable.
  • Write Amplification: A proporção entre o total de bytes escritos no disco físico e os bytes escritos pela aplicação.
  • Write Stall: Pausa forçada nas escritas da aplicação para permitir que o compaction reduza o backlog de arquivos.
  • XPoint (3D XPoint): Tecnologia de memória persistente que preenche a lacuna entre RAM e SSD.
  • Zero-copy: Técnica que permite ler dados do disco direto para a rede sem passar pelo espaço de usuário.
  • Zstandard (Zstd): Algoritmo de compressão de alta performance muito usado em SSTables.

13. Apêndice B: Referências e Leituras Recomendadas

Papers Fundamentais

  • O'Neil, P., et al. (1996). The Log-Structured Merge-Tree (LSM-Tree). Acta Informatica, 33(4), 351-385. (O paper que deu o nome à tecnologia).
  • Rosenblum, M., & Ousterhout, J. K. (1992). The Design and Implementation of a Log-Structured File System. ACM TOCS.
  • Chang, F., et al. (2006). Bigtable: A Distributed Storage System for Structured Data. OSDI. (A base para o HBase e Cassandra).

Livros e Guias

  • Kleppmann, M. (2017). Designing Data-Intensive Applications. O'Reilly. (O capítulo 3 explica LSM Trees com clareza incomparável).
  • Petrov, A. (2019). Database Internals. O'Reilly. (Um mergulho profundo na implementação de motores de storage).
  • RocksDB Wiki. RocksDB Tuning Guide. github.com/facebook/rocksdb.

Comunidade e Casos de Uso

  • Netflix Tech Blog. How we use RocksDB for extreme scale caching.
  • Uber Engineering. Building a high-throughput storage engine with RocksDB.
  • Cloudflare. Using RocksDB to power the edge.

14. FAQ: Perguntas Frequentes (Expandido)

1. LSM Tree é um banco de dados? Não, é uma estrutura de dados ou uma arquitetura de armazenamento usada dentro de bancos de dados como Cassandra ou RocksDB.

2. O que acontece se o computador desligar e os dados estiverem no MemTable? Os dados são recuperados através do Write-Ahead Log (WAL), que é um arquivo de log gravado no disco antes de qualquer dado entrar na memória RAM.

3. Por que deletar um dado no Cassandra o faz ocupar MAIS espaço inicialmente? Porque você está inserindo um Tombstone (um novo registro). O espaço só será liberado quando o Compaction remover o dado antigo e o tombstone permanentemente.

4. Posso usar LSM Trees em discos mecânicos (HDDs)? Sim! Elas foram criadas justamente para extrair o máximo de performance dos HDDs, transformando procuras lentas em escritas sequenciais rápidas.

5. Qual a diferença entre Leveled e Size-Tiered Compaction? Size-Tiered foca em minimizar o atraso na escrita; Leveled foca em tornar as leituras o mais rápidas possível.

6. O Bloom Filter alguma vez erra? Ele pode dar um "Falso Positivo" (dizer que o dado está lá quando não está), mas nunca um "Falso Negativo". Ou seja, ele nunca perde um dado.

7. Por que o RocksDB é tão popular? Por sua extrema flexibilidade e performance. Ele permite tunar quase cada aspecto de como os dados são lidos e gravados.

8. O que é Write Amplification? É o fenômeno onde o banco escreve o mesmo dado no disco várias vezes durante os processos de reorganização (compaction).

9. LSM Trees podem ser usadas para SQL? Sim. O projeto MyRocks é uma implementação do MySQL que usa o RocksDB como motor de armazenamento em vez do InnoDB.

10. Como o SSD afeta as LSM Trees? Os SSDs eliminam o custo de busca, tornando as leituras muito mais rápidas, mas o padrão sequencial das LSM Trees ainda é vital para aumentar a vida útil do SSD (Write Endurance).

11. O que é o 'Write-Ahead Log' (WAL)? É um arquivo onde cada operação de escrita é registrada antes de ser aplicada ao MemTable. Ele serve para reconstruir os dados da memória caso o sistema sofra uma queda repentina.

12. LSM Trees podem sofrer de fragmentação? Sim, tanto fragmentação de arquivos no sistema operacional quanto fragmentação de dados (muitas versões da mesma chave em arquivos diferentes). O compaction é o processo que "desfragmenta" o banco.

13. Qual a relação entre LSM Trees e a 'LGPD'? A imutabilidade dificulta a "deleção imediata". Para estar em conformidade, é necessário garantir que o processo de compaction ocorra dentro de um prazo aceitável para remover fisicamente os dados deletados.

14. Por que o RocksDB é usado na borda (Edge)? Porque ele é extremamente eficiente em termos de consumo de recursos e pode ser configurado para rodar em dispositivos com pouca memória, como gateways de IoT ou nós de CDN.

15. O que é um 'Level 0' stall? É quando o banco de dados para de aceitar novas escritas porque há muitos arquivos no Nível 0 esperando por compaction. Isso evita que o número de arquivos cresça tanto que as leituras se tornem impossíveis.

16. Posso ter múltiplos MemTables? Sim, o RocksDB permite configurar uma fila de MemTables imutáveis que esperam para ser gravados no disco, o que ajuda a absorver picos de escrita ainda maiores.

17. O que é o 'Forward Scan' e 'Backward Scan'? São operações de percorrer os dados em ordem crescente ou decrescente. Em LSM Trees, o Backward Scan costuma ser um pouco mais lento devido à forma como os dados são organizados nos blocos.

18. Como saber se meu Bloom Filter está pequeno demais? Monitore a métrica de "Bloom Filter Useful". Se ela for baixa, significa que o filtro está deixando passar muitas consultas para o disco que acabam resultando em "não encontrado".

19. O que é 'Tiered Storage' em LSM? É a técnica de colocar os níveis mais baixos (L0, L1) em SSDs rápidos e os níveis mais altos (L5, L6), que são menos acessados, em HDDs mais baratos ou no S3.

20. Existe algum banco de dados que mistura B-Trees e LSM? Sim, alguns bancos modernos usam estruturas híbridas. O Fractal Tree é um exemplo clássico que tenta pegar o melhor dos dois mundos.

21. Qual o papel da CPU no Compaction? O compaction é uma tarefa pesada de CPU devido à necessidade de descompactar, ordenar e re-comprimir os dados. Em sistemas modernos, isso pode ser um gargalo de processamento.

22. O que é o 'IngestSSTable' no RocksDB? É uma funcionalidade que permite carregar arquivos SSTable pré-gerados externamente diretamente para o banco de dados sem passar pelo MemTable, ideal para migrações massivas de dados.

23. O que é 'Delta Encoding' em SSTables? É uma técnica de compressão onde, em vez de armazenar chaves inteiras, o banco armazena apenas a diferença entre a chave atual e a anterior, economizando muito espaço em chaves ordenadas.

24. Como o LSM lida com 'Range Scans'? Ele utiliza um Merge Iterator. Esse iterador lê do MemTable e de todos os SSTables relevantes simultaneamente, fazendo um "merge sort" em tempo real para entregar os dados na ordem correta ao usuário.

25. O que é 'Write Stall'? É um mecanismo de defesa. Quando o background compaction não consegue acompanhar o ritmo de escrita, o banco deliberadamente atrasa as novas escritas para evitar que o sistema fique instável.

26. LSM Trees funcionam bem com compressão Zstandard (Zstd)? Sim, o Zstd é muito usado no RocksDB pois oferece um excelente equilíbrio entre taxa de compressão e uso de CPU, sendo ideal para os níveis mais altos (L4-L6).

27. Qual o impacto de um 'Clock Skew' em sistemas LSM distribuídos? Pode causar problemas na resolução de conflitos (Last Write Wins). Se os relógios dos servidores não estiverem sincronizados, um dado antigo com um timestamp maior pode "vencer" um dado novo.

28. O que é o 'Block Restart Interval'? No RocksDB, as chaves são prefix-compressed. A cada X chaves (intervalo de restart), a compressão para e uma chave completa é gravada para permitir buscas binárias rápidas dentro do bloco.

29. Posso desativar o WAL? Sim, para cargas onde a perda de dados em um crash é aceitável (ex: cache), desativar o WAL aumenta drasticamente o throughput de escrita.

30. Por que as LSM Trees são chamadas de 'Write-Optimized'? Porque elas transformam o custo de escrita (latência) em uma tarefa de background (compaction), permitindo que a aplicação receba um "OK" quase instantâneo após gravar na memória.

Glossário Expandido

  • Block Cache: Cache em memória RAM para os blocos de dados dos SSTables.
  • Bloom Filter: Estrutura probabilística para evitar leituras inúteis no disco.
  • Checkpoint: Captura de um estado consistente do banco de dados no disco.
  • Column Family: Divisão lógica de dados dentro de um mesmo banco de dados LSM.
  • Compaction: Processo de mesclar SSTables, removendo dados obsoletos e otimizando a leitura.
  • Computational Storage: Tecnologia que move o processamento para dentro do dispositivo de armazenamento.
  • Data Block: Unidade básica de armazenamento de dados dentro de um SSTable.
  • Direct I/O: Técnica de acessar o disco sem passar pelo cache do sistema operacional.
  • Flush: Ato de gravar o conteúdo do MemTable no disco como um novo SSTable.
  • Index Block: Bloco que contém o índice para busca rápida dentro de um SSTable.
  • LCS (Leveled Compaction Strategy): Estratégia que organiza SSTables em níveis fixos.
  • LSM Tree (Log-Structured Merge Tree): Arquitetura que otimiza escritas convertendo I/O aleatório em sequencial.
  • MemTable: Estrutura de memória (árvore ou skip-list) que recebe as escritas iniciais.
  • Merge Sort: Algoritmo base usado durante o compaction para unir arquivos ordenados.
  • Prefix Compression: Técnica de omitir prefixos repetidos de chaves para economizar espaço.
  • Read Amplification: Quantidade de trabalho extra feito pelo disco para satisfazer uma leitura.
  • SSTable (Sorted String Table): Arquivo imutável e ordenado gravado no disco.
  • STCS (Size-Tiered Compaction Strategy): Estratégia que agrupa arquivos por tamanho similar.
  • Tombstone: Marcador especial indicando que uma chave foi deletada.
  • WA (Write Amplification): Razão entre os dados gravados no disco e os dados enviados pela aplicação.
  • WAL (Write-Ahead Log): Registro sequencial de todas as operações antes de entrarem na memória.
  • ZNS (Zoned Namespaces): Padrão de interface para SSDs que se alinha perfeitamente com a natureza das LSM Trees.
  • Shared-nothing: Arquitetura onde cada core da CPU possui seu próprio recurso, eliminando locks.
  • Learned Index: Uso de modelos matemáticos ou ML para substituir índices tradicionais.
  • Write Stall: Pausa forçada nas escritas para permitir que o sistema se recupere de sobrecarga.
  • Last Write Wins (LWW): Política comum de resolução de conflitos baseada em timestamps.
  • Immutable: Característica de dados que não podem ser alterados após gravados.
  • Sequential I/O: Padrão de acesso ao disco onde os dados são lidos/gravados de forma contínua.
  • Flash Translation Layer (FTL): Camada de software interna do SSD que gerencia o mapeamento de blocos.

Este artigo foi desenvolvido com base em rigorosas fontes acadêmicas e documentação oficial de sistemas de alta performance.

Imagem de tecnologia relacionada ao artigo log-structured-storage-lsm-trees