Coordenação sem um centro
Um protocolo de fofoca é o jeito como um grupo grande de máquinas chega a um acordo sobre fatos a respeito de si mesmo quando nenhuma máquina está no comando. Para entender, comece olhando o que esta aplicação faz no lugar disso.
O que esta aplicação faz no lugar disso
Aqui há três mecanismos de coordenação, e os três são o mesmo mecanismo.
# config/queue.yml (resumido)
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "default"
threads: 3
polling_interval: 0.1
# mais dois grupos de workers, cada um com a própria fila e intervalo
# config/cable.yml (produção)
polling_interval: 0.1.seconds
message_retention: 1.day
# config/deploy.yml (seção proxy)
healthcheck:
path: /up
interval: 5
Um despachante de jobs pergunta ao banco a cada segundo. Um grupo de workers pergunta mais ou menos a cada décimo de segundo. O ouvinte do cable em cada processo do servidor pergunta a cada décimo de segundo, tenha ele quantos assinantes de WebSocket tiver. E, durante um deploy, o proxy pergunta ao contêiner novo a cada cinco segundos até ele responder.
Ninguém avisa ninguém de nada. Cada participante pergunta sem parar a uma única autoridade compartilhada, o banco ou a própria aplicação, e essa autoridade é todo o mecanismo de coordenação.
Por que isso funciona aqui
Funciona porque a autoridade existe e é alcançável: um nó PostgreSQL, dois processos Puma, um proxy.
Neste tamanho, consultar um armazenamento compartilhado é o projeto certo, e vale dizer isso com clareza em vez de tratar como limitação. É simples, não tem modos de falha próprios além dos do armazenamento e custa uma consulta por intervalo por participante.
Esse último ponto é onde a coisa para de funcionar. Custo por participante vezes o número de participantes é a propriedade de escala, e ela vai bem com três e é impossível com três mil.
flowchart TB
subgraph "esta aplicação"
W1["worker"] --> DB[("banco compartilhado")]
W2["despachante"] --> DB
C1["ouvinte do cable"] --> DB
P["proxy, durante um deploy"] --> APP["/up"]
end
DB --> N["uma autoridade. todos perguntam a ela. ninguém conta nada"]
Quando não há autoridade
A fofoca parte desta premissa: não existe um armazenamento compartilhado que todo nó alcance, ou alcançá-lo custa mais do que a coordenação vale.
Isso acontece por dois motivos. Um é a escala: mil nós consultando um coordenador fazem dele o gargalo e o ponto único de falha. O outro é a geografia: nós em três continentes não conseguem todos alcançar um armazenamento a baixo custo, como o curso de nível Sênior "Arquitetura: banco de dados multi-região" mediu, com cerca de 200ms por ida e volta entre São Paulo e Frankfurt.
Então os nós conversam entre si. Cada nó, de tempos em tempos, escolhe alguns pares ao acaso e troca o que sabe: quem está vivo, quem entrou, quem saiu e qual versão da lista de membros ele tem.
Ninguém tem o quadro completo em nenhum momento, e todo mundo chega a ele rápido.
A troca que se faz
| Autoridade central (esta aplicação) | Fofoca | |
|---|---|---|
| Quem sabe a verdade | Um armazenamento | Ninguém, depois todos |
| Custo por nó | Uma consulta por intervalo | Algumas mensagens por intervalo |
| Custo no centro | Cresce com o número de nós | Não existe centro |
| Falha do centro | Tudo para | Não se aplica |
| Atualidade | Tão atual quanto o intervalo | Converge em O(log N) rodadas |
| Complexidade | Quase nenhuma | Considerável |
Leia a última linha. A fofoca não é melhor. É o que você usa quando a linha de cima ficou inaceitável.
Essa linha só fica inaceitável numa escala de que esta aplicação está muito longe. É esse o enquadramento justo deste curso: você está aprendendo o formato de uma solução para um problema que precisa saber reconhecer, e não inventar.
A única coisa para levar mesmo neste tamanho
Intervalos de consulta são um orçamento de coordenação, e as pessoas costumam escolhê-los sem ter um.
O polling_interval: 0.1 no Solid Cable significa que o ouvinte de cada processo do servidor faz dez consultas por segundo, para sempre, aconteça algo ou não. Com WEB_CONCURRENCY: 2, são vinte consultas por segundo: uma carga conhecida e limitada. O número que importa é consultas por segundo por participante vezes o número de participantes. Vale calcular uma vez, porque a escala em que isso deixa de ir bem chega sem nenhuma mudança no código.
Pontos-chave
- Esta aplicação coordena consultando uma autoridade compartilhada: o despachante a cada 1s, workers e ouvintes do cable a cada 0,1s, e a checagem de saúde do deploy a cada 5s.
- Neste tamanho, consultar um armazenamento compartilhado é o projeto certo, e custa uma consulta por intervalo por participante.
- A premissa da fofoca é que não existe autoridade compartilhada alcançável, por causa da escala ou da geografia.
- Na fofoca, os nós trocam o que sabem com alguns pares aleatórios. Ninguém tem o quadro todo, e todos convergem.
- Intervalos de consulta são um orçamento de coordenação. Calcule consultas por segundo vezes participantes uma vez, porque a escala chega sem o código mudar.
Continue com a aula 2
Como a fofoca se espalha
O laço de quatro passos da fofoca, a tolerância a falhas dos pares aleatórios e a convergência em log N rodadas.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.