Skip to content

Protocolli di Consenso

“L’accordo fa la forza, il disaccordo fa la storia.” — Nel cluster di Pasta Protocol, preferiamo la forza.

Il consenso distribuito è il problema più antico e più difficile dei sistemi distribuiti. Pasta Protocol lo risolve con tre protocolli distinti, ognuno con le sue garanzie, i suoi compromessi e il suo carattere culinario. La scelta del protocollo giusto è come scegliere il sugo giusto: dipende dal piatto, dall’occasione e da quanto tempo avete a disposizione.

Tutti e tre i protocolli espongono la stessa interfaccia base ConsensusProtocol, ma con comportamenti radicalmente diversi sotto carico, in presenza di partizioni di rete e in caso di nodi lenti o assenti.

Interfaccia Base

export interface ConsensusProtocol {
readonly name: string;
readonly minQuorum: number; // frazione minima di nodi richiesti
propose<T>(value: T, options?: ProposeOptions): Promise<ConsensusResult<T>>;
observe<T>(topic: string, handler: (result: ConsensusResult<T>) => void): Unsubscribe;
status(): Promise<ProtocolStatus>;
}
export interface ConsensusResult<T> {
readonly accepted: boolean;
readonly value: T | undefined;
readonly round: number;
readonly participants: string[];
readonly duration: number; // ms
}

Protocollo Pesto

Velocità ligure. Accordo a 2/3. Ispirato al pesto genovese: rapido da preparare, intenso nel sapore, non richiede cottura. Il Protocollo Pesto è il protocollo di default di Pasta Protocol per operazioni che necessitano di bassa latenza e possono tollerare un margine di nodi assenti.

Caratteristiche

ProprietàValore
Quorum minimo2/3 dei nodi attivi
Latency tipica15–40 ms
Fault toleranceTollera fino a 1/3 nodi guasti
ConsistenzaLinearizable
Throughput~8.000 op/s per nodo

Quando usarlo

  • Aggiornamenti di configurazione del cluster
  • Leader election e rotazione
  • Operazioni di write che richiedono bassa latenza
  • Qualsiasi operazione dove la velocità è più critica della certezza assoluta

Limitazioni

Il Pesto non funziona se più di 1/3 dei nodi non risponde entro il timeout configurato. In quel caso il sistema lancia un errore VESUVIO e la proposta viene annullata. Questo è il comportamento corretto: meglio nessun accordo che un accordo sbagliato.

API

import { Pasta } from 'pasta-protocol';
const pesto = Pasta.consensus.pesto({
timeout: 2000, // ms per round
rounds: 3, // max round prima di VESUVIO
quorumFraction: 0.67, // 2/3 default
});
// Proposta base
const risultato = await pesto.propose('nuovo-leader', {
topic: 'cluster.leader',
ttl: 30_000,
});
if (risultato.accepted) {
console.log(`Accordo raggiunto in ${risultato.duration}ms`);
console.log(`Partecipanti: ${risultato.participants.join(', ')}`);
} else {
// Gestione errore: i nodi non hanno raggiunto il quorum
console.error('PEPERONCINO: quorum non raggiunto');
}
// Osservazione continua
const unsubscribe = pesto.observe<string>('cluster.leader', (result) => {
if (result.accepted) {
console.log(`Nuovo leader eletto: ${result.value}`);
}
});
// Stato del protocollo
const stato = await pesto.status();
console.log(`Nodi attivi: ${stato.activeNodes}/${stato.totalNodes}`);

Configurazione in .ricetta

consenso:
protocollo: pesto
timeout: 2000
rounds: 3
quorumFraction: 0.67
retryOnVesuvio: true
retryDelay: 500

Selezione del Protocollo

La scelta del protocollo giusto dipende dal vostro scenario. Come regola generale:

  • Pesto per operazioni frequenti dove la velocità è prioritaria
  • Genovese per operazioni rare ma critiche dove non si può sbagliare
  • Ragu per workflow complessi, multi-step, che devono sopravvivere ai guasti

È possibile usare protocolli diversi per operazioni diverse nello stesso cluster. La configurazione in .ricetta supporta un protocollo di default e override per topic specifici.

consenso:
default: pesto
override:
'schema.*': genovese
'onboarding.*': ragu
'leader.*': pesto