Il Pattern Transactional Outbox: Pubblicazione Affidabile di Eventi nei Microservizi

Il Pattern Transactional Outbox: Pubblicazione Affidabile di Eventi nei Microservizi

Nelle moderne architetture guidate dagli eventi (Event-Driven Architecture), i microservizi emettono costantemente eventi (OrderCreated, PaymentProcessed) per comunicare in modo disaccoppiato.

Tuttavia, pubblicare eventi in modo affidabile solleva una sfida fondamentale: Come garantire che l’aggiornamento del database locale e la pubblicazione dell’evento abbiano entrambi successo o falliscano insieme?

Se un microservizio aggiorna il proprio database (PostgreSQL, MySQL) e subito dopo tenta di inviare un messaggio a un broker (Apache Kafka, RabbitMQ), una disconnessione di rete o un timeout può causare un’incoerenza nei dati.

Per risolvere questo problema si utilizza il Pattern Transactional Outbox.


Il Problema della Doppia Scrittura (Dual-Write Problem)

Quando un servizio esegue due scritture distinte:

  1. Salvataggio dei dati aziendali nel database locale.
  2. Invio dell’evento al message broker.
Diagramma del problema di doppia scrittura

Se il commit del database ha successo ma la trasmissione di rete verso Kafka fallisce, l’ordine è salvato ma i servizi a valle non riceveranno mai la notifica. Risultato: Incoerenza dei dati.


Cos’è il Pattern Transactional Outbox?

Il pattern sfrutta le transazioni locali ACID dei database relazionali.

Invece di inviare direttamente il messaggio via rete, il servizio scrive il payload dell’evento in una tabella dedicata Outbox Table all’interno della stessa transazione locale che salva l’entità di business.

Grazie alle proprietà ACID, entrambe le scritture vengono confermate insieme o annullate insieme.

In seguito, un processo in background (Message Relay) legge la tabella Outbox e invia gli eventi al message broker.


Strategie di Relaying: Polling Publisher vs. CDC (Debezium)

Confronto tra Polling Publisher e CDC Debezium

1. Polling Publisher

Un processo pianificato interroga periodicamente i record non elaborati (SELECT * FROM outbox_events WHERE processed = FALSE), li invia a Kafka e aggiorna lo stato.

  • Vantaggi: Semplice da implementare.
  • Svantaggi: Latenza dovuta all’intervallo di polling e carico sul database.

2. Change Data Capture (CDC con Debezium)

Debezium legge direttamente i log di transazione del database (PostgreSQL WAL) e trasmette le modifiche in tempo reale a Kafka.

  • Vantaggi: Latenza quasi zero e nessun sovraccarico sull’applicazione.
  • Svantaggi: Richiede l’infrastruttura Kafka Connect e Debezium.

Conclusione

Il Pattern Transactional Outbox è fondamentale per garantire la consistenza eventuale e l’affidabilità nei sistemi a microservizi.