
Modelo rápido de escrita move trabalho para outro lugar no sistema
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.