1/13 Como seu sistema lida com mensagens duplicadas?
Quando alguém ou alguma empresa falar enfaticamente que seu broker de estimação garante Exactly-Once Message Delivery (ou Processing) de forma mágica ou "plug and play", simplesmente DESCONFIE!
2/13 Os brokers mais populares geralmente oferecem esta feature, mas aqui estou falando mais especificamente de SQS FIFO e Kafka Transactions.
Exactly-Once Message Processing é um problema complexo de se resolver no mundo de mensageria e sistemas distribuídos.
3/13 Brokers até suportam esta semântica em um certo grau… DESDE QUE certos critérios (condições) sejam obedecidos pelas pontas da integração. Estou falando dos producers e consumers! 🤷🏻♀️
Apesar dos brokers fazerem seu melhor, nada vem de graça nesse mundo de sistemas distribuídos!
4/13 Não me entenda errado, soluções como SQS FIFO e Kafka Transactions são MUITO boas, quase o estado da arte, mas não são mágicas.
Elas facilitarão a vida de arquitetos(as) e desenvolvedores(as) com relação a algumas preocupações de design DESDE QUE todas as pontas cooperem com a solução.
5/13 🟡 No caso do SQS FIFO, seu sistema precisa necessariamente garantir:
-
O producer não pode enviar mensagens duplicadas fora da janela de 5min;
-
O consumer não pode falhar em deletar a mensagem da fila que ele acabou de processar;
6/13 Se seu sistema não pode ser desenhado para lidar com estes 2 casos, você não será capaz de usar FIFO queues para Exactly-once processing, pelo menos não como você gostaria.
Seus producers devem evitar duplicatas fora (além) da janela de 5min OU seus consumers devem descartar mensagens duplicadas.
7/13 Não se engane, todo broker tem suas limitações e tradeoffs relacionadas a Exactly-once Processing. Dessa forma, vamos refletir um pouco sobre a solução do Kafka, a Kafka Transactions.
8/13 🟡 No caso do Kafka Transactions, a solução se baseia num sistema fechado (closed system).
Isso quer dizer que enquanto toda a leitura, processamento e escrita de estado estiver dentro do Kafka e, sob controle dele, as garantias são mantidas - não à toa funciona bem para Stream processing.
9/13 Contudo, em sistemas transacionais, OLTP e mais corporativos a coisa pode complicar um pouco mais.
Basta um sistema externo (ou side-effects) entrar na equação que tudo pode acabar em problemas de inconsistência, estado corrompido ou resultados não deterministicos.
10/13 Neste caso, boa parte da complexidade fica no lado consumer.
O consumer precisa garantir a cooperação destes sistemas externos e seus efeitos colaterais para manter as garantias de Exactly-Once Processing do Kafka, por exemplo, projetando p/ idempotência, atomicidade ou mesmo de-duplication.
11/13 ⭐️ Exactly-once Processing é uma solução end-to-end e sua aplicação TAMBÉM precisa ser desenhada para não violar estas propriedades.
Isso inclui parte da sua aplicação que implementa a produção de mensagens e, principalmente, o consumo delas.
12/13 ⭐️ Na prática, a forma como alcançamos Exactly-Once Delivery é fingindo que ela acontece por meio de dinâmicas e técnicas comuns em At-Least Once.
Falo de mensagens idempotentes, que podem ser aplicadas N vezes sem efeito colateral indesejado, ou removendo esta necessidade via de-duplication.
13/13 No fim, o que estou querendo dizer é que soluções em sistemas distribuídos são mais resilientes, tolerantes a falhas e possuem maior grau de corretude (correctness) quando todas as pontas cooperam entre si.
No caso de mensageria, falo do Broker, do Producer e do Consumer.
A imagem exibida expressa os 3 tipos de semânticas utilizadas em mensageria: At-Most Once Delivery, At-Least Once Delivery e, por fim, Exactly-Once Delivery.