stamatios
← Voltar ao feed
Modelo rápido de escrita move trabalho para outro lugar no sistema
Dev & Engenharia

Modelo rápido de escrita move trabalho para outro lugar no sistema

resumo de ~3 min

O tradeoff fundamental: velocidade vs. durabilidade

Todo motor de armazenamento precisa decidir o que deve terminar antes de confirmar uma escrita ao cliente. As opções formam um espectro: retornar após copiar bytes na memória (rápido, mas perde dados em crash de kernel), esperar um fdatasync() num SSD local (sobrevive a crash de processo/kernel, mas não à perda do host), ou aguardar replicação remota (sobrevive a falhas maiores, mas adiciona latência de rede).

Como um PUT chega ao SSD local

Numa implementação com WAL (write-ahead log), o write() copia bytes para o page cache do kernel, mas só o fdatasync() garante que os dados chegaram ao dispositivo. O autor destaca que O_DIRECT e io_uring não mudam esse ponto de durabilidade - apenas otimizam o caminho de I/O.

Um único flush pode cobrir múltiplas escritas: o WAL writer agrupa registros num batch (por bytes, número de escritas ou tempo) e chama fdatasync() uma vez para todos. Isso melhora throughput, mas o primeiro request do batch espera mais, e um erro de flush falha o batch inteiro.

Mantendo a escrita além do host

Retornar sucesso após o SSD local torna o banco stateful - o scheduler não pode mover o processo para outra máquina sem risco de perder escritas confirmadas. As alternativas são:

  • Volume de rede durável: parece um dispositivo de bloco, mas o serviço de storage mantém cópias fora do host. O fdatasync() inclui ida e volta pela rede.
  • Object storage (ex: S3): após um PUT bem-sucedido, o serviço assume a durabilidade. O banco pode deixar o upload para depois (mais rápido, mas cria janela de perda) ou esperar o upload antes de confirmar (mais lento, mas sem janela).
  • WAL replicado: o líder envia a entrada para seguidores e espera maioria durável (ex: 2 de 3). Adiciona latência de rede e um segundo sync de disco, mas sobrevive à perda de um servidor.

Replicação traz coordenação

Com WAL replicado, o sistema precisa resolver eleição de líder, reparo de logs divergentes, snapshots, adição/remoção de nós e monitoramento de atraso de replicação - nada disso aparece na latência de uma escrita saudável. O artigo menciona Raft como exemplo: o líder registra o termo atual e a posição no log, envia aos seguidores e commita após maioria salvar no disco.

Leituras rápidas exigem índice e limpeza

Replay do WAL não torna GET barato. É necessário um índice (hash, B-tree ou LSM) para localizar o valor atual. Cada abordagem deixa bytes antigos para trás após deletes ou substituições, exigindo limpeza posterior (compaction, garbage collection).

Big O esconde a latência de durabilidade

A complexidade assintótica de um PUT é a mesma (O(key + payload)) independentemente do caminho, mas o trabalho antes do sucesso muda drasticamente: um flush local vs. um round-trip HTTP vs. transferência de rede + sync em maioria. O autor conclui que números de performance só são úteis quando acompanhados do ponto de sucesso e do percentil.

Reflexão final

LLMs aceleram a escrita de uploaders, loops de limpeza e logs replicados, mas não podem decidir quando é seguro retornar sucesso, o que um timeout significa ou qual crash pode perder dados. Essas decisões precisam ser explicitadas e testadas.