DEV Community

Matheus de Camargo Marques
Matheus de Camargo Marques

Posted on

Elixir Enchiridium — Tomo VI: A Batalha

Com base na pesquisa realizada, aqui está o início do Tomo VI — A Batalha.


AVISO: esta série é uma fantasia satírica baseada em fatos reais sobre Elixir. Nada aqui deve ser levado ao pé da letra. Ao final de cada capítulo, os fatos por trás da lenda são revelados. Tags: #satire #humor #elixir #enchiridium


Elixir Enchiridium — Tomo VI: A Batalha

Prefácio do Tomo

No Tomo I, contamos a história de como Elixir nasceu. No Tomo II, abrimos a máquina. No Tomo III, abrimos o OTP. No Tomo IV, abrimos a sintaxe. No Tomo V, abrimos o ecossistema.

Agora, no Tomo VI, vamos abrir a batalha.

Distribuir sistemas é fácil. Distribuir sistemas que não caem é uma batalha. Cada nó é um soldado. Cada mensagem é um mensageiro. Cada partição de rede é uma emboscada. A BEAM foi projetada para essa guerra desde o início. Mas projetar para a guerra não significa vencer todas as batalhas.

Este tomo é sobre concorrência, distribuição, clusters, CAP, partições de rede, supervisão distribuída, e todos os desafios de construir sistemas que nunca caem. Cada capítulo parte de um fato verificável e o transforma em uma crônica fantástica.

São cem capítulos. O sexto tomo de dez.

Comecemos pelo começo: o que significa, afinal, ser distribuído?


Capítulo 1 — Distributed Erlang: A Rede que Não É uma Biblioteca

A lenda diz que, em outras linguagens, distribuir um sistema é uma decisão. Você adiciona uma biblioteca. Você configura um serviço. Você reza para funcionar. No Elixir, distribuir é uma herança. A BEAM já nasceu distribuída. Você não adiciona distribuição. Você a descobre.

A verdade é que distribuição no BEAM não é uma biblioteca acoplada por cima, é embutida no runtime. Um sistema Erlang distribuído consiste em um número de runtime systems Erlang comunicando entre si. Cada runtime system é chamado de nó. Um nó é um runtime system Erlang que recebeu um nome, usando a flag -name (nomes longos) ou -sname (nomes curtos) na linha de comando. A distribuição é implementada usando sockets TCP/IP. Uma vez que você entende o que ela oferece, muitas coisas que você normalmente usaria — filas, camadas de RPC, service meshes — começam a parecer workarounds para problemas que você não tem.

A lenda diz que, na primeira vez que um programador iniciou dois nós e os conectou, ele perguntou: "Onde está o servidor de mensagens?" O instrutor respondeu: "Não tem. A BEAM é o servidor."

O fato por trás da lenda: A distribuição no BEAM é embutida no runtime, não uma biblioteca acoplada. Um sistema Erlang distribuído consiste em nós — runtime systems Erlang nomeados com -name ou -sname. A distribuição usa sockets TCP/IP. Muitas coisas que você usaria (filas, RPC, service meshes) parecem workarounds para problemas que a BEAM já resolve.

Gancho: A rede é embutida. Mas como dois nós se encontram?


Capítulo 2 — O Cookie: O Segredo que Autentica os Nós

A lenda diz que, para dois nós se conectarem, eles precisam compartilhar um segredo. Um cookie. Um cookie mágico. Se os cookies batem, os nós se cumprimentam. Se não batem, os nós se ignoram. O cookie é a senha. O cookie é a chave. O cookie é a lei.

A verdade é que, para dois nós Erlang se conectarem, eles precisam compartilhar um cookie — uma string secreta usada para autenticação. O cookie é definido com a flag --cookie ou no arquivo .erlang.cookie. Se os cookies não corresponderem, os nós não se conectam. O cookie é uma forma de autenticação simples, mas se alguém obtiver o cookie, pode se conectar ao cluster. Ataques ao mecanismo de distribuição Erlang são um vetor de segurança conhecido.

A lenda diz que, na primeira vez que um programador esqueceu o cookie, ele perguntou: "Por que não conecta?" O instrutor respondeu: "Porque você não sabe o segredo." O programador perguntou: "Como assim?" O instrutor respondeu: "O cookie é o segredo."

O fato por trás da lenda: Para dois nós Erlang se conectarem, precisam compartilhar um cookie — uma string secreta usada para autenticação. O cookie é definido com --cookie ou no arquivo .erlang.cookie. Se os cookies não corresponderem, os nós não se conectam.

Gancho: O cookie autentica. Mas há uma coisa que conecta os nós automaticamente: o Libcluster.


Capítulo 3 — Libcluster: O Feitiço que Junta os Nós (Parte 7)

A lenda diz que, para formar um cluster Elixir, você precisa de magia. Você roda libcluster e, de repente, todos os nós se encontram, se cumprimentam e começam a trabalhar juntos. Se um nó morre, os outros sentem falta. Se um nó nasce, os outros dão boas-vindas. O Libcluster é o mestre de cerimônias do arquipélago.

A verdade é que Libcluster fornece um mecanismo para formar automaticamente clusters de nós Erlang, com adesão estática ou dinâmica. Ele fornece um mecanismo de publish/subscribe para eventos de cluster, para que você possa ser notificado quando membros entram ou saem, e fornece um sistema de estratégias plugável. Ele suporta várias estratégias: EPMD, Kubernetes, Gossip, DNS, Rancher, e outras. A estratégia Cluster.Strategy.Gossip, por exemplo, usa o protocolo multicast gossip para formar um cluster dinamicamente.

A lenda diz que, na primeira vez que um programador usou Libcluster, ele perguntou: "Como isso funciona?" O instrutor respondeu: "Magia com estratégia."

O fato por trás da lenda: Libcluster forma clusters de nós Erlang automaticamente, com adesão estática ou dinâmica. Fornece publish/subscribe para eventos de cluster e um sistema de estratégias plugável. Suporta EPMD, Kubernetes, Gossip, DNS, Rancher.

Gancho: O feitiço junta. Mas há uma coisa que explica os limites: o Teorema CAP.


Capítulo 4 — CAP: O Teorema que a BEAM Ignora (ou Não) (Parte 6)

A lenda diz que, quando os aliens criaram a BEAM, eles leram o Teorema CAP e disseram: "Vamos escolher AP." E assim fizeram. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP.

A verdade é que a maioria das bibliotecas distribuídas do Elixir (Phoenix Pub/Sub, Horde, Swarm, Delta CRDTs) fica do lado AP do Teorema CAP. Elas preferem disponibilidade a consistência estrita. No entanto, existe o Paxtor, uma biblioteca Elixir para construir sistemas distribuídos CP (Consistent and Partition-tolerant) no BEAM. O Paxtor é baseado no PaxosKV, que fornece uma camada de consenso baseada no algoritmo Basic Paxos.

A lenda diz que, na primeira vez que um programador ouviu falar do CAP, ele perguntou: "Qual lado é melhor?" O instrutor respondeu: "Depende do que você não pode perder."

O fato por trás da lenda: A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP. O Paxtor é uma biblioteca CP que usa Paxos.

Gancho: O teorema explica. Mas há uma coisa que a BEAM faz melhor: tolerância a falhas.


Capítulo 5 — Tolerância a Falhas: A Filosofia que Virou Benchmark (Parte 7)

A lenda diz que, num benchmark acadêmico, o Elixir foi comparado a outras linguagens concorrentes sob condições de falha. O resultado? "Elixir atingiu o maior throughput e a menor variabilidade de throughput sob condições de falha". Os aliens aplaudiram. Os humanos tomaram café.

A verdade é que a tolerância a falhas da BEAM é um dos seus pontos mais fortes. Processos isolados, supervisores, árvores de supervisão, "let it crash" — tudo isso faz com que sistemas BEAM se recuperem de falhas de forma quase automática. Um benchmark acadêmico comparou a tolerância a falhas em Elixir e outras linguagens distribuídas e concorrentes (Scala com Akka, Go com Proto.Actor). O Elixir atingiu o maior throughput e a menor variabilidade sob condições de falha. No entanto, a latência de reconexão aumenta em escala devido a gargalos de coordenação centralizada. O Scala com Akka demonstrou a recuperação de falhas e latência de reconexão mais estáveis em todas as escalas. O Go com Proto.Actor ofereceu throughput competitivo em implantações de pequena escala, mas exibiu limitações de escalabilidade na detecção e recuperação de falhas.

A lenda diz que, na primeira vez que um programador viu um sistema se recuperar sozinho, ele perguntou: "Como?" O instrutor respondeu: "Supervisores."

O fato por trás da lenda: A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Um benchmark acadêmico mostrou que Elixir atinge o maior throughput e a menor variabilidade sob condições de falha, embora a latência de reconexão aumente em escala. Scala/Akka teve a recuperação mais estável; Go/Proto.Actor teve limitações de escalabilidade.

Gancho: A tolerância é a base. Mas há uma coisa que mantém os processos vivos: os supervisores.


Capítulo 6 — Supervisor: As Babás que Nunca Dormem (Parte 8)

A lenda diz que os supervisores são babás que dão mamadeira para processos órfãos. Se um processo morre, a babá chora, pega um novo processo no berçário e coloca no lugar. A estratégia one_for_one significa que ela só troca uma fralda por vez. A rest_for_one é quando ela troca todas as fraldas da fileira. A one_for_all é quando ela surta e reinicia o berçário inteiro.

A verdade é que supervisores são processos que monitoram outros processos (chamados de processos filhos) e os reiniciam quando falham. Supervisores formam árvores de supervisão que fornecem tolerância a falhas e capacidades de auto-recuperação. A árvore de supervisão é um modelo de estruturação de processos baseado na ideia de workers e supervisores. Workers são processos que realizam computação e trabalho real. Supervisores são processos que monitoram workers. A árvore de supervisão é um arranjo hierárquico de código em supervisores e workers, que torna possível projetar e programar software tolerante a falhas.

A lenda diz que, na primeira vez que um programador viu uma árvore de supervisão, ele perguntou: "Quantos níveis?" O instrutor respondeu: "Quantos você precisar."

O fato por trás da lenda: Supervisores monitoram processos filhos e os reiniciam quando falham. Formam árvores de supervisão que fornecem tolerância a falhas e auto-recuperação. Workers realizam trabalho real; supervisores monitoram workers.

Gancho: As babás cuidam. Mas há um processo que serve: o GenServer.


Capítulo 7 — GenServer: O Mordomo que Serve Estado em Bandejas (Parte 8)

A lenda diz que um GenServer é um mordomo chamado Alfred que guarda o estado do seu sistema em uma bandeja de prata. Quando você chama GenServer.call, ele responde "Pois não, senhor" e executa a função. Se você usar GenServer.cast, ele anota o recado e vai fazer depois, sem pressa.

A verdade é que GenServer é um comportamento do OTP para construir servidores genéricos. Ele encapsula estado e concorrência, permitindo que você defina callbacks para lidar com chamadas síncronas e assíncronas. GenServer é um dos blocos de construção fundamentais de aplicações Elixir. O callback code_change/3 é usado para migrar o estado durante hot code upgrades.

A lenda diz que, na primeira vez que um programador criou um GenServer, ele perguntou: "Preciso implementar tudo?" O instrutor respondeu: "Só os callbacks."

O fato por trás da lenda: GenServer é um comportamento do OTP para construir servidores genéricos. Encapsula estado e concorrência, com callbacks para chamadas síncronas e assíncronas.

Gancho: O mordomo serve. Mas há uma coisa que persiste: o Ecto.


Capítulo 8 — O Scheduler: O Juiz que Nunca Dorme (Parte 3)

A lenda diz que o scheduler da BEAM é um juiz que nunca dorme. Ele olha para cada processo e diz: "Você já rodou o suficiente. Próximo." Os processos obedecem. Se não obedecessem, o scheduler os interromperia.

A verdade é que o scheduler da BEAM emprega um mecanismo de preempção, prioridade e agendamento que rapidamente alterna entre processos disponíveis para criar a ilusão de que todos estão executando simultaneamente. Ele usa o conceito de reduções. Uma redução representa uma unidade de trabalho realizada pela BEAM, abrangendo operações fundamentais como aplicação de função, cálculos aritméticos ou passagem de mensagens. O scheduler mantém o controle das reduções executadas por cada processo, preemptando um processo quando ele atinge um certo número de reduções. Cada processo recebe cerca de 4000 reduções antes de ser preemptado. O conceito de "redução" em Erlang é herdado de sua ancestralidade Prolog, onde cada passo de execução é chamado de "goal-reduction".

A lenda diz que o scheduler é justo porque nunca deixou um processo monopolizar a CPU. Nem mesmo o processo que queria calcular o último dígito de Pi.

O fato por trás da lenda: O scheduler da BEAM usa preempção baseada em reduções. Uma redução é uma unidade de trabalho (chamada de função, operação aritmética, passagem de mensagens). Cada processo recebe cerca de 4000 reduções antes de ser preemptado. O conceito de redução vem do Prolog.

Gancho: O scheduler distribui. Mas há uma coisa que explica os limites: o Teorema CAP.


Capítulo 9 — Horde: O Supervisor que Não Conhece Fronteiras

A lenda diz que o Horde é um supervisor. Mas não é um supervisor comum. Ele supervisiona através de nós. Ele distribui processos. Ele mantém um registro. Ele é construído sobre DeltaCrdt. Ele é eventualmente consistente. Ele nunca perde um processo. Ele nunca deixa um nó sozinho.

A verdade é que Horde é composto por Horde.Supervisor, um supervisor distribuído, e Horde.Registry, um registro distribuído. Horde é construído sobre DeltaCrdt. Como Horde é construído sobre CRDTs, ele é eventualmente consistente (em vez de imediatamente consistente), embora sincronize seu estado com seus vizinhos de forma bastante agressiva. A associação ao cluster no Horde é totalmente dinâmica; nós podem ser adicionados e removidos a qualquer momento e o Horde continuará operando conforme esperado. Horde.Supervisor também usa um anel de hash para limitar quaisquer condições de corrida a momentos em que a associação ao cluster está mudando. Horde é eventualmente consistente, o que significa que pode garantir disponibilidade e tolerância a partição. Quando a associação ao cluster do Horde é constante, ele também garante consistência. Se um nó falha (ou se torna inalcançável), o Horde.Supervisor redistribuirá os processos entre os nós restantes.

A lenda diz que, na primeira vez que um programador usou Horde, ele perguntou: "O que acontece se um nó cair?" O instrutor respondeu: "Os processos se mudam."

O fato por trás da lenda: Horde é um supervisor distribuído e registro construído sobre DeltaCrdt. É eventualmente consistente, garantindo disponibilidade e tolerância a partição. Usa anel de hash para limitar condições de corrida. Se um nó cai, os processos são redistribuídos.

Gancho: O supervisor distribui. Mas há uma coisa que coordena nomes globalmente: o módulo global.


Capítulo 10 — O Módulo Global: O Cartório dos Nomes Distribuídos

A lenda diz que o módulo global é um cartório. Ele registra nomes. Ele notifica todos os nós. Ele monitora nós. Ele mantém a rede totalmente conectada. Ele é o cartório dos nomes distribuídos. Ele nunca perde um nome. Ele nunca deixa um nó sozinho.

A verdade é que o módulo global fornece registro de nomes globalmente distribuído. A capacidade de registrar nomes globalmente é um conceito central na programação de sistemas Erlang distribuídos. O módulo global consiste em serviços para: registro global de nomes, monitoramento de nós, e manutenção da rede totalmente conectada. Esses serviços são controlados através do processo global, que existe em cada nó. O global é iniciado automaticamente quando um nó é iniciado. A partir do OTP 25, o global irá, por padrão, prevenir partições sobrepostas devido a problemas de rede, desconectando ativamente de nós que relatam ter perdido conexões com outros nós.

A lenda diz que, na primeira vez que um programador usou global, ele perguntou: "Onde está o nome?" O instrutor respondeu: "No cartório. E o cartório está em todo lugar."

O fato por trás da lenda: O módulo global fornece registro de nomes globalmente distribuído. Monitora nós e mantém a rede totalmente conectada. A partir do OTP 25, previne partições sobrepostas desconectando ativamente nós que perderam conexões.

Gancho: O cartório registra. Mas há uma coisa que testa partições: o Schism.


Capítulo 11 — Schism: O Feiticeiro que Parte a Rede

A lenda diz que o Schism é um feiticeiro. Ele parte a rede. Ele simula netsplits. Ele testa partições. Ele usa um truque com cookies. Ele nunca erra. Ele nunca deixa uma partição passar despercebida.

A verdade é que Schism é uma ferramenta de teste de partição para Elixir. Ele fornece uma API simples para testar partições entre nós BEAM. O motivo de existência do Schism é testar netsplits entre BEAMs de forma rápida e fácil, e ele usa um truque rudimentar com cookies para atingir esse objetivo. Schism é usado em conjunto com ferramentas como local_cluster e propcheck.

A lenda diz que, na primeira vez que um programador usou Schism, ele perguntou: "O que é um netsplit?" O instrutor respondeu: "É quando a rede se parte ao meio. E o Schism te ajuda a testar isso."

O fato por trás da lenda: Schism é uma ferramenta de teste de partição para Elixir. Fornece API para testar partições entre nós BEAM. Usa um truque com cookies. Usado com local_cluster e propcheck.

Gancho: O feiticeiro parte. Mas há uma coisa que lida com partições: o Horde.


Capítulo 12 — Net Splits: A Emboscada que Ninguém Vê

A lenda diz que os net splits são emboscadas. A rede se parte. Os nós ficam presos em lados opostos. Cada lado acha que o outro morreu. Cada lado reinicia seus processos. Quando a rede volta, há dois exércitos de processos. A batalha é sangrenta. A batalha é confusa. A batalha é a pior parte de ser distribuído.

A verdade é que lidar com net splits é um dos maiores desafios de sistemas distribuídos. A natureza da distribuição Erlang torna net splits parciais um problema não solucionável com o mecanismo nativo, e a única forma de mitigar é usar ferramentas como Partisan. Em caso de partição de rede, cada partição reinicia os processos que estavam rodando na outra parte, assumindo que aquela parte está caída. Quando a partição é curada, pode haver múltiplas instâncias do mesmo processo rodando. Para prevenir que duas instâncias do mesmo processo permaneçam rodando após a cura de um netsplit, você precisa registrar cada processo filho com um nome único. A ferramenta global_supervisor lida com isso reiniciando processos na outra partição e exigindo registro único.

A lenda diz que, na primeira vez que um programador viu um net split, ele perguntou: "O que aconteceu?" O instrutor respondeu: "A rede se partiu. E agora há dois de tudo."

O fato por trás da lenda: Net splits parciais são um problema não solucionável com a distribuição Erlang nativa. Ferramentas como Partisan ajudam a mitigar. Quando a partição é curada, pode haver múltiplas instâncias do mesmo processo. global_supervisor lida com isso reiniciando processos na outra partição e exigindo registro único.

Gancho: A emboscada é real. Mas há uma coisa que ajuda a lidar com ela: o global_supervisor.


Capítulo 13 — GlobalSupervisor: O General que Reinicia os Processos

A lenda diz que o global_supervisor é um general. Ele supervisiona processos. Mas não é um supervisor comum. Ele distribui processos pelo cluster. Em caso de partição de rede, cada partição reinicia os processos da outra parte. Quando a partição é curada, ele verifica se há duplicatas. Se houver, ele mata uma. O general nunca deixa dois exércitos iguais.

A verdade é que global_supervisor é um supervisor que distribui dinamicamente os filhos pelo cluster. Em caso de partição de rede, cada partição reinicia os processos filhos que estavam rodando na outra parte, assumindo que aquela parte está caída. Uma vez que a partição é curada, pode haver múltiplas instâncias do mesmo filho rodando. Para prevenir que duas instâncias do mesmo filho permaneçam rodando após a cura de um netsplit, você precisa registrar cada processo filho com um nome único.

A lenda diz que, na primeira vez que um programador usou global_supervisor, ele perguntou: "E se houver dois?" O instrutor respondeu: "O general mata um."

O fato por trás da lenda: global_supervisor distribui filhos pelo cluster. Em caso de partição, cada partição reinicia os processos da outra. Após a cura, pode haver múltiplas instâncias. Registrar cada filho com nome único previne duplicatas.

Gancho: O general comanda. Mas há uma coisa que conecta tudo: o PubSub.


Capítulo 14 — Phoenix.PubSub Distribuído: O Megafone que Atravessa Oceanos

A lenda diz que o Phoenix.PubSub é um megafone. Mas não é um megafone comum. Ele atravessa oceanos. Ele conecta nós. Ele transmite mensagens para todos os processos inscritos, não importa em qual nó eles estejam. O megafone nunca falha. O megafone nunca se perde.

A verdade é que Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. Ele foi projetado para ser flexível e suportar múltiplos backends. Há dois backends oficialmente suportados. Phoenix.PubSub permite que desenvolvedores realizem dispatch customizado passando um módulo dispatcher, que é responsável pelas entregas locais de mensagens. Ele é usado pelo Phoenix para transmitir atualizações do LiveView. Em um cluster, o PubSub distribui mensagens entre os nós usando a distribuição Erlang.

A lenda diz que, na primeira vez que um programador usou PubSub em cluster, ele perguntou: "Como a mensagem chegou lá?" O instrutor respondeu: "Pelo megafone. E o megafone tem alcance global."

O fato por trás da lenda: Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. Suporta múltiplos backends. Permite dispatch customizado. Usado pelo Phoenix para transmitir atualizações do LiveView. Distribui mensagens entre nós em cluster.

Gancho: O megafone transmite. Mas há uma coisa que registra presenças: o Phoenix.Presence.


Capítulo 15 — Phoenix.Presence Distribuído: O Vigia que Vê Tudo

A lenda diz que o Phoenix.Presence é um vigia. Ele vê quem está online. Ele vê quem entrou. Ele vê quem saiu. Ele replica essa informação para todos os nós. Se um nó cai, os outros sentem falta. Se um nó volta, os outros dão boas-vindas. O vigia nunca dorme. O vigia nunca esquece.

A verdade é que Phoenix.Presence fornece rastreamento de presença para processos e canais. É um behaviour que fornece recursos como buscar presenças para um tópico e lidar com diffs de eventos de join e leave em tempo real. Usar este módulo define um supervisor e permite que o módulo chamador implemente o behaviour Phoenix.Tracker, que inicia um processo tracker para lidar com informações de presença. Presence.track registra o processo do canal como presença para o ID do usuário do socket, com um mapa de metadados. Em cluster, Presence usa PubSub para replicar informações de presença entre nós.

A lenda diz que, na primeira vez que um programador usou Presence em cluster, ele perguntou: "Como isso funciona?" O instrutor respondeu: "PubSub."

O fato por trás da lenda: Phoenix.Presence fornece rastreamento de presença para processos e canais. Define um supervisor e usa Phoenix.Tracker com Phoenix.PubSub para broadcast de atualizações de presença. Em cluster, usa PubSub para replicar informações.

Gancho: O vigia vê. Mas há uma coisa que coordena transações: o :global.


Capítulo 16 — OTP 25: A Mudança no global que Ninguém Viu

A lenda diz que, no OTP 25, uma mudança silenciosa aconteceu. O módulo global começou a prevenir partições sobrepostas. Ele desconecta ativamente de nós que relatam ter perdido conexões com outros nós. A mudança foi sutil. A mudança foi importante. A mudança salvou clusters.

A verdade é que, a partir do OTP 25, o módulo global irá, por padrão, prevenir partições sobrepostas devido a problemas de rede, desconectando ativamente de nós que relatam ter perdido conexões com outros nós. Isso resolve um problema antigo onde partições parciais podiam levar a visões inconsistentes do cluster. Antes do OTP 25, os desenvolvedores tinham que lidar com isso manualmente ou usar ferramentas externas.

A lenda diz que, na primeira vez que um programador ouviu falar disso, ele perguntou: "Por que ninguém me contou?" O instrutor respondeu: "Porque estava na documentação."

O fato por trás da lenda: A partir do OTP 25, o módulo global previne partições sobrepostas desconectando ativamente de nós que relatam ter perdido conexões com outros nós. Isso resolve um problema antigo de visões inconsistentes do cluster.

Gancho: A mudança foi silenciosa. Mas há uma coisa que continua: a batalha contra a entropia.


Capítulo 17 — Partisan: A Alternativa à Distribuição Nativa

A lenda diz que o Partisan é uma alternativa. Ele não usa a distribuição nativa do Erlang. Ele usa seu próprio protocolo. Ele é mais escalável. Ele é mais configurável. Ele é mais complexo. Ele nunca substitui a BEAM. Ele apenas a complementa.

A verdade é que Partisan é uma biblioteca que fornece uma alternativa à distribuição Erlang nativa, com foco em escalabilidade e configurabilidade. Ele foi criado para resolver alguns dos problemas da distribuição totalmente conectada do Erlang, que pode se tornar um gargalo em clusters grandes. Partisan oferece diferentes topologias de rede e estratégias de comunicação. A distribuição Erlang totalmente conectada significa que um sistema com N nós precisa manter O(n) conexões TCP/IP ativas, o que induz tráfego de rede significativo acima de 40 nós.

A lenda diz que, na primeira vez que um programador ouviu falar de Partisan, ele perguntou: "Por que não usar a distribuição nativa?" O instrutor respondeu: "Porque ela não escala para 100 nós."

O fato por trás da lenda: Partisan é uma alternativa à distribuição Erlang nativa, focada em escalabilidade e configurabilidade. A distribuição totalmente conectada do Erlang requer O(n) conexões TCP/IP, o que se torna um gargalo acima de 40 nós.

Gancho: A alternativa existe. Mas há uma coisa que sempre foi o problema: o teorema CAP.


Capítulo 18 — CAP na Prática: O que Ninguém te Conta

A lenda diz que o Teorema CAP é um teorema. Mas na prática, ele é uma escolha. Você escolhe consistência ou disponibilidade. Você escolhe tolerância a partição ou nada. E a BEAM escolheu. A BEAM escolheu ser AP. A BEAM escolheu estar disponível. A BEAM escolheu tolerar partições. A BEAM escolheu ser a espinha dorsal de sistemas que nunca caem.

A verdade é que a maioria das bibliotecas distribuídas do Elixir (Phoenix Pub/Sub, Horde, Swarm, Delta CRDTs) fica do lado AP do Teorema CAP. Elas preferem disponibilidade a consistência estrita. No entanto, existe o Paxtor, uma biblioteca CP que usa Paxos. A escolha entre AP e CP é fundamental. AP significa que o sistema continua disponível mesmo se houver partições de rede, mas os dados podem estar temporariamente inconsistentes. CP significa que o sistema garante consistência, mas pode ficar indisponível durante partições.

A lenda diz que, na primeira vez que um programador perguntou "Qual lado escolher?", o instrutor respondeu: "Escolha o que você não pode perder."

O fato por trás da lenda: A maioria das bibliotecas distribuídas do Elixir é AP. O Paxtor é CP. AP significa disponibilidade sobre consistência; CP significa consistência sobre disponibilidade.

Gancho: A escolha é sua. Mas há uma coisa que a BEAM sempre escolheu: disponibilidade.


Capítulo 19 — Distributed Supervision: A Supervisão que Atravessa Nós

A lenda diz que a supervisão distribuída é uma arte. Você tem uma árvore de supervisão em um nó. Você tem outra em outro nó. Eles não se conhecem. Mas eles se coordenam. Se um nó cai, o outro assume. Se um nó volta, o outro compartilha. A supervisão distribuída é a coisa mais difícil de fazer certo. E ninguém te conta isso.

A verdade é que a supervisão distribuída é um dos maiores desafios de sistemas distribuídos. Existem bibliotecas como distributed_supervisor que fornecem um dynamic supervisor especializado projetado para funcionar transparentemente em ambientes Erlang/Elixir distribuídos. Ele oferece distribuição automática de processos entre nós conectados, redistribuição de processos quando nós entram ou saem do cluster, capacidades de seleção/atribuição de nó por processo, e tolerância a falhas com recuperação automática entre nós. No entanto, a supervisão distribuída não é nativa do OTP e requer bibliotecas externas ou padrões cuidadosos.

A lenda diz que, na primeira vez que um programador tentou supervisionar através de nós, ele perguntou: "Por que não funciona?" O instrutor respondeu: "Porque a supervisão não atravessa nós sozinha."

O fato por trás da lenda: A supervisão distribuída não é nativa do OTP. Bibliotecas como distributed_supervisor fornecem dynamic supervisor especializado para ambientes distribuídos. Oferece distribuição automática, redistribuição, seleção de nó e recuperação.

Gancho: A arte é difícil. Mas há uma coisa que sempre foi a base: a árvore de supervisão.


Capítulo 20 — A Árvore de Supervisão Distribuída: A Família que Não Sabe que é uma Família

A lenda diz que a árvore de supervisão distribuída é uma família que não sabe que é uma família. Cada nó tem sua própria árvore. Cada árvore acha que é a única. Mas quando se encontram, elas se tornam uma. Uma família que atravessa oceanos. Uma família que nunca se desfaz.

A verdade é que a árvore de supervisão é um modelo de estruturação de processos baseado na ideia de workers e supervisores. Workers são processos que realizam computação e trabalho real. Supervisores são processos que monitoram workers. A árvore de supervisão é um arranjo hierárquico de código em supervisores e workers, que torna possível projetar e programar software tolerante a falhas. Em sistemas distribuídos, cada nó pode ter sua própria árvore de supervisão, e bibliotecas como Horde permitem que essas árvores se coordenem através de nós.

A lenda diz que, na primeira vez que um programador viu duas árvores de supervisão se coordenando, ele perguntou: "Como elas se conhecem?" O instrutor respondeu: "Pelo Horde. Pelo Registry. Pelo PubSub."

O fato por trás da lenda: A árvore de supervisão é um modelo de estruturação de processos. Em sistemas distribuídos, cada nó pode ter sua própria árvore, e bibliotecas como Horde permitem coordenação entre nós.

Gancho: A família é distribuída. Mas há uma coisa que sempre foi o desafio: a partição de rede.


Epílogo Parcial do Tomo VI

Vinte capítulos. Uma batalha. Mil processos. E um brasileiro que ouviu um sussurro.

Este foi o começo do Tomo VI — A Batalha, com fatos verificados. Ainda faltam 80 capítulos para completar este tomo. Nos próximos, vamos explorar: Distributed Erlang nativo, :pg e :pg2, Swarm, Syn, Registry distribuído, clustering com Kubernetes, segurança em distribuição, e muitos outros tópicos.

Até lá.


Agora, sério: A distribuição no BEAM é embutida no runtime, não uma biblioteca acoplada. Nós Erlang se conectam via TCP/IP e compartilham um cookie para autenticação. Libcluster forma clusters automaticamente. O Teorema CAP se aplica: a maioria das bibliotecas do Elixir é AP; o Paxtor é CP. A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Supervisores formam árvores de supervisão. GenServer encapsula estado. O scheduler usa reduções para preempção. Horde é um supervisor distribuído construído sobre DeltaCrdt. O módulo global registra nomes globalmente e, a partir do OTP 25, previne partições sobrepostas. Schism testa netsplits. Net splits parciais são um problema não solucionável com a distribuição Erlang nativa. global_supervisor lida com partições. Phoenix.PubSub distribui mensagens entre nós. Phoenix.Presence rastreia presenças. Partisan oferece uma alternativa à distribuição nativa. A supervisão distribuída não é nativa e requer bibliotecas externas. As capivaras quânticas não são reais — mas deveriam ser. Este artigo é uma fantasia satírica baseada em fatos. Mantenha o aviso para não enganar ninguém.

Top comments (0)