Pular para o conteúdo principal

Write-Ahead Log

Descrição​

O Write-Ahead Log (WAL) é um arquivo de log somente com acréscimos (append-only) em disco no qual cada mudança de estado é registrada como um comando antes de ser aplicada às estruturas de dados em memória ou aos arquivos de dados. Só depois que o registro foi gravado (e sincronizado com o disco, via flush/fsync) o servidor aplica a mudança e responde ao cliente. Por isso o log também é chamado de commit log.

Se o servidor cai e reinicia, ele perdeu o estado em memória, mas não o log. Na recuperação, o nó lê o log do início (ou do último ponto de verificação) e reexecuta os comandos na ordem, reconstruindo o estado exato de antes da falha. Cada entrada costuma ter um identificador sequencial (índice), o tipo de dado e o conteúdo do comando, e frequentemente um checksum para detectar gravações parciais.

O padrão é a base de vários outros do catálogo: o Segmented Log divide o log em arquivos menores, o Low-Water Mark descarta o que não é mais necessário e o Replicated Log o replica entre nós. Aparece no Cassandra (commit log), no ZooKeeper (log de transações), no etcd (WAL com Raft) e no Kafka, cujo armazenamento é essencialmente um log particionado.

Problemas que resolve​

  • Garantir durabilidade: depois que o servidor aceitou uma ação, ela precisa ser concluída mesmo que ele falhe e reinicie sem o estado em memória.
  • Evitar escritas aleatórias custosas em estruturas de dados no caminho crítico, trocando-as por acréscimos sequenciais.
  • Permitir reconstruir o estado após uma queda reexecutando os comandos registrados.
  • Dar uma ordem total e um identificador a cada mudança, o que sustenta replicação e recuperação.

Quando usar​

  • Bancos de dados, brokers e serviços de coordenação que mantêm estado em memória ou em estruturas complexas e precisam sobreviver a reinicializações.
  • Quando é preciso replicar a sequência de mudanças para outros nós, como base de um Replicated Log.
  • Quando a durabilidade de cada escrita confirmada é requisito (por exemplo, com fsync antes do ack).

Quando evitar​

  • Dados efêmeros ou facilmente recriáveis (caches), em que perder o estado em uma queda é aceitável.
  • Quando a latência do fsync por escrita é inaceitável e a perda de uma janela recente de dados é tolerada.
  • Sistemas que já delegam a durabilidade a um armazenamento externo confiável, tornando o log redundante.

Trade-offs​

GanhoCusto / Risco
Durabilidade forte e recuperação determinística após falhasCada escrita paga o custo de acréscimo e fsync em disco, o que limita a vazão e adiciona latência
Escritas sequenciais, rápidas em discos e SSDsO log cresce sem parar e exige segmentação e limpeza (Segmented Log e Low-Water Mark)
Ordem total das mudanças, útil para replicaçãoRecuperação lenta se o log for longo e não houver snapshots ou pontos de verificação
  • Escritas parciais: use checksums por entrada para descartar a cauda corrompida na recuperação.
  • Política de flush: sincronizar a cada escrita é seguro e lento; agrupar escritas (group commit) ou sincronizar periodicamente troca durabilidade por desempenho.
  • Concorrência: a gravação sequencial costuma ser feita por uma única thread, como no Singular Update Queue.
  • Idempotência: como a reexecução pode repetir comandos, os comandos devem poder ser reaplicados com segurança.

Diagrama​

O servidor grava o comando no log em disco antes de alterar o estado em memória e só então responde. Após uma falha, o estado é reconstruído reexecutando o log.

Padrões relacionados​

Referência​