Construindo um serviço de log distribuido: Write-Ahead log
Tags: go, backend, architecture, braziliandevs
Published: 2023-06-12 06:21:26

## Introdução

Sistemas distribuídos é um dos temas do qual tenho muito interesse, para começar uma trilha de estudos sobre, resolvi começar com uma abordagem prática, construindo algo real que proporcione uma visão geral e seja próximo da minha atual realidade, optei pelo livro [Distributed Services with Go: Your Guide to Reliable, Scalable, and Maintainable Systems](https://www.amazon.com/Distributed-Services-Go-Reliable-Maintainable/dp/1680507605) do [Travis Jeffery](https://www.linkedin.com/in/travisjeffery), onde a proposta do livro é entender sistemas distribuídos ao construir um

Essa série faz parte do estudo prático sobre a jornada de construção do serviço de log distribuído proposto no livro, onde consiste em armazenar, compartilhar e processar dados ordenadamente, operações atômicas usando log.

Seguindo um caminho parecido do qual [Travis Jeffery](https://www.linkedin.com/in/travisjeffery) fez ao construir o [jocko](https://github.com/travisjeffery/jocko), uma implementação do Kafka em Go.

Repositório do projeto: [gmarcial/gproglog](https://github.com/gmarcial/gproglog)

## Logs

A ideia da construção do serviço é entender os conceitos essenciais por trás do sistemas distribuídos, como os logs.

Começaremos pelo core do serviço, o write-ahead log, solução utilizada em sistemas distribuídos para atomicidade e durabilidade, replicação/distribuição dos dados, backup, recuperação de falha, consenso e mais.

Alguns exemplos de sistemas que usam: Bancos de dados, filas, algoritmos de consenso como paxos e raft, storage engine, change data capture (cdc) e data-stream.

O Write-Ahead Log é uma abstração de armazenamento append-only de registros em sequência, ordenada pela ordem da ocorrência dos registros e cada registro recebe um identificador único e sequencial, indexando o registro a partir do deslocamento no momento que o registro ocorreu.

Novos registros são adicionados ao final e a leitura ocorre no início do log, seguindo a sequência e ordem que os registros aconteceram, do mais antigo para o mais novo.

![Representação visual do log.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11ldkj8vqah81u1kjbj3.png)

Para uma explicação profunda e detalhada sobre o conceito, sugiro a leitura do artigo [The Log: What every software engineer should know about real-time data's unifying abstraction](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying) do [Jay Kreps](https://www.linkedin.com/in/jaykreps), um dos criadores do Kafka, precursor de muito do que temos hoje de event-stream, stream processing e real-time a partir das experiências da [engenharia do Linkedin](https://engineering.linkedin.com/).

No artigo ele aborda não somente o conceito, mas que os logs são o coração dos sistemas distribuídos, uso, integração, real-time stream processing, surgimento do kafka e como esse conceito está presente no nosso dia a dia, sendo o kafka um log como serviço utilizado amplamente.

Outro artigo que recomendo, muito interessante e que é correlacionado, é o [Stream processing, Event sourcing, Reactive, CEP… and making sense of it all](https://martin.kleppmann.com/2015/01/29/stream-processing-event-sourcing-reactive-cep.html) do [Martin Kleppmann](https://www.linkedin.com/in/martinkleppmann).

### Solução

![Componentes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vozldhth23lrxzb7944o.png)

O serviço será cliente do Log para gerenciamento dos registros.

A solução consiste em uma API para operar o log, essencialmente a escrita e leitura dos registros que são estruturados em segmentos.

Para a escrita de um novo registro o `Log` irá delegar para o `Segment` ativo, onde o processo envolve armazenar o registro através da `Store` e o indexar através do `Index` para posterior leitura.

Da mesma forma, para a leitura de um registro o `Log` irá delegar para o `Segment` ativo, onde o processo envolve encontrar o registro no `Index` e caso ele exista o recuperar na `Store` através do seu deslocamento.

Conforme o limite do `Segment` atual é atingido, um novo é criado e indicado como ativo.

Visão de como o log é estruturado, sendo representado de verde o `Segment` ativo:

![estrutura](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kywa5plo2w162e0r6c28.png)

Referência da implementação:
- [Store](https://github.com/gmarcial/gproglog/blob/main/internal/log/store.go).
- [Index](https://github.com/gmarcial/gproglog/blob/main/internal/log/index.go).
- [Segment](https://github.com/gmarcial/gproglog/blob/main/internal/log/segment.go).
- [Log](https://github.com/gmarcial/gproglog/blob/main/internal/log/log.go).

## Próximos passos

Com a implementação do log os próximos passos na construção do serviço é prover e expor essas funcionalidades a na rede, para que possa operar.

Isso envolve vários passos até a distribuição e deploy propriamente dito no decorrer da série de estudos do livro.

## Extras

### Livro I Heart Logs: Event Data, Stream Processing, and Data Integration

Livro do [Jay Kreps](https://www.linkedin.com/in/jaykreps) sobre logs, aparente evolução e continuação do seu post sobre logs, ainda não li, mas parece interessante.

Até o momento em que escrevo, é possível obter o livro gratuitamente através da Confluent nesse [link](https://www.confluent.io/ebook/i-heart-logs-event-data-stream-processing-and-data-integration/?utm_medium=sem&utm_source=google&utm_campaign=ch.sem_br.nonbrand_tp.prs_tgt.content-search_mt.xct_rgn.latam_lng.eng_dv.all_con.ihl&utm_term=i%20love%20logs&creative=&device=c&placement=&gad=1&gclid=CjwKCAjw4ZWkBhA4EiwAVJXwqQYjKEoFRAZiaVBGUp6mwn6U8Vharcf7X_6bLSXl2o7d86Qpm7mYyxoCWMoQAvD_BwE), a alternativa é [comprar](https://www.amazon.com/Heart-Logs-Stream-Processing-Integration/dp/1491909382?language=pt_BR&currency=BRL).

### Valencia: A Log-Structured On-Disk Hash
[Valencia](https://github.com/jkreps/valencia), implementação de um Log do [Jay Kreps](https://www.linkedin.com/in/jaykreps), muito parecida com a versão do [Travis Jeffery](https://www.linkedin.com/in/travisjeffery).

### Patterns of Distributed Systems por Unmesh Joshi
[Unmesh Joshi](https://twitter.com/unmeshjoshi) tem um post no blog [martinfowler](https://martinfowler.com/) sobre [padrões de sistemas distribuídos](https://martinfowler.com/articles/patterns-of-distributed-systems/), neles contém vários relacionados a log, onde vários são aplicados na solução do serviço do livro como:
- [Write-Ahead Log](https://martinfowler.com/articles/patterns-of-distributed-systems/wal.html#examples).
- [Segmented Log](https://martinfowler.com/articles/patterns-of-distributed-systems/log-segmentation.html).
- [Low-Water Mark](https://martinfowler.com/articles/patterns-of-distributed-systems/low-watermark.html).
- [Replicated Log](https://martinfowler.com/articles/patterns-of-distributed-systems/replicated-log.html).
- [Singular Update Queue](https://martinfowler.com/articles/patterns-of-distributed-systems/singular-update-queue.html).


## Referências

[Distributed Services with Go: Your Guide to Reliable, Scalable, and Maintainable Systems.](https://www.amazon.com/Distributed-Services-Go-Reliable-Maintainable/dp/1680507605)

[The Log: What every software engineer should know about real-time data's unifying abstraction.](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying)

[Stream processing, Event sourcing, Reactive, CEP… and making sense of it all.](https://martin.kleppmann.com/2015/01/29/stream-processing-event-sourcing-reactive-cep.html)

[Patterns of Distributed Systems](https://martinfowler.com/articles/patterns-of-distributed-systems/)