A Rede DHT

Como é que centenas de servidores independentes sem diretório central se encontram, concordam sobre onde os dados vivem e encaminham pedidos eficientemente? O Hashiverse usa uma tabela de hash distribuída Kademlia — a mesma família de algoritmos usada pelo BitTorrent, IPFS e pela camada de descoberta de pares do Ethereum — adaptada aos padrões de acesso de uma rede social.

O anel

Cada entidade no Hashiverse — servidores, utilizadores, publicações, hashtags — tem um identificador de 256 bits derivado do seu hash Blake3. Estes IDs vivem num anel: o espaço de endereços fecha-se em 2256. A "distância" entre dois IDs é o XOR dos seus padrões de bits, uma métrica que dá ao anel propriedades úteis de encaminhamento.

Cada servidor mantém ligações a outros servidores cujos IDs estão próximos do seu na distância XOR, mais ligações a distâncias exponencialmente crescentes (os k-buckets do Kademlia). Esta estrutura significa que qualquer servidor pode encaminhar uma consulta para o servidor mais próximo de qualquer ID-alvo em O(log n) saltos, em que n é o número de servidores na rede.

Origem: kademlia.rs

Onde os dados vivem

Um balde de publicações é guardado nos servidores cujos IDs estão mais próximos do location_id do balde — um hash derivado do tipo de balde, do ID base (utilizador, hashtag ou publicação), e da janela temporal. Isto significa:

Não há índice mestre. Nenhum servidor sabe onde está tudo. Cada servidor sabe onde estão as coisas próximas dele, e como encaminhar para coisas que estão longe.

Distribuição de carga

Os hashtags populares seriam um gargalo se todas as publicações de um hashtag aterrassem indefinidamente no mesmo punhado de servidores. O Hashiverse distribui esta carga usando rotação de chaves baseada em épocas temporais: o location ID para um balde de hashtag desloca-se ao longo do tempo, por isso épocas diferentes aterram em partes diferentes do anel — servidores diferentes. Todos os location IDs de cronologias rodam com cadência mensal; mas as cronologias com mais movimento transbordam automaticamente para baldes de granularidade crescente.

O sistema de baldes é hierárquico: baldes de 1 mês subdividem-se em semanais, depois diários, depois de 6 horas, horários, de 15 minutos, de 5 minutos e de 1 minuto. O carregamento da cronologia atravessa esta hierarquia recursivamente — começando grosseiro e descendo para baldes mais finos apenas onde existe conteúdo. Uma cronologia com atividade esparsa carrega de forma barata; uma cronologia densa carrega eficientemente porque cada balde pode ser obtido em paralelo.

Origem: buckets.rs, recursive_bucket_visitor.rs

Abstração de transporte

O protocolo é agnóstico ao transporte. As traits TransportFactory, TransportServer e TransportServerHandler em hashiverse-lib/src/transport/ definem a interface; as implementações são trocadas sem tocar na lógica do protocolo:

Os testes de integração tiram bastante partido disto: um teste que verifique o comportamento de auto-recuperação, o encaminhamento DHT ou a propagação de publicações pode correr inteiramente em memória, com timing determinístico, sem portas e sem limpeza.

Orquestração do test-harness

O binário test-harness arranca um servidor primário (para bootstrap) mais um número configurável de servidores secundários, num único processo, usando o JoinSet do Tokio, todos partilhando o mesmo cancellation token para um shutdown gracioso. O orquestrador HashiverseServer inicializa o Kademlia, gera handlers de transporte e gere a descoberta de pares.

Origem: hashiverse-integration-tests/src/bin/test_harness.rs