- Modern technologies won't support it (RabbitMQ, Kafka, etc.);
- This is a form of using Inter-Process Communication in a synchronized way and this reduces availability;
- All participants of the distributed transaction need to be avaiable for a distributed commit, again: reduces availability.
Implementing business transactions that span multiple services is not straightforward. Distributed transactions are best avoided because of the CAP theorem. Moreover, many modern (NoSQL) databases don’t support them. The best solution is to use the Saga Pattern.
[...]
One of the most well-known patterns for distributed transactions is called Saga. The first paper about it was published back in 1987 and has it been a popular solution since then.
There are a couple of different ways to implement a saga transaction, but the two most popular are:
- Events/Choreography: When there is no central coordination, each service produces and listen to other service’s events and decides if an action should be taken or not;
- Command/Orchestration: when a coordinator service is responsible for centralizing the saga’s decision making and sequencing business logic;
Message Ordering e sua complexidade
Message Ordering eh das coisas mais escorregadias de se fazer em Mensageira.
Não importa seu broker, seja um #RabbitMQ, #ActiveMQ ou #Kafka.
Mesmo quando se tem 1-único-Producer e 1-único-Consumer ainda assim existem edge-cases que podem levar a mensagens fora de ordem e consequentemente inconsistência dos dados 🤡
No fim, devemos abraçar um príncipio chamado de “The End-to-End Principle” (E2E Principle).
Quando falo de E2E Principle, estou falando de trazer alguma “inteligência” para as pontas do seu sistema, para seu producer e consumer, e se nortear por:
abrace At-Least Once Delivery;
não confie no seu Broker Delivery Order;
comutatividade em vez ordenação;
idempotência e/ou deduplication;
1) abrace At-Least Once Delivery
É praticamente impossível implementar a semântica Exactly-Once Delivery, não acredite cegamente no que os vendors te falam!
O que podemos fazer eh fingir sua execução implementando mecanismos que a façam acontecer em cima da semântica At Least-Once Delivery, como o uso de idempotência, deduplication, transações etc.
2) não confie no seu Broker Delivery Order
A ordem que as mensagens entram e saem no seu broker tem pouca ou nenhuma importância, confiar nela eh a melhor forma de se dar mal.
O que importa de fato eh a ordem de negócio das mensagens (Business event order), pois eh com base nela que vc vai desenhar e implementar sua solução.
3) comutatividade em vez ordenação
Dado que a ordem de mensagens não pode ser confiada nem garantida pelo broker, aceite que as mensagens podem (e eventualmente irão) chegar fora de ordem.
Portanto, programe seu código em consumers para isso, não espere o pior acontecer.
4) idempotência e deduplication
Embora ambos os conceitos sejam fáceis de entender, eles não necessariamente são fáceis de implementar.
Especialmente se você lida com sistemas externos, ou seja, sua lógica causa efeitos colaterais em outros serviços, como RDBMS, cache ou um processo qualquer.
Concluindo
Enfim, sem E2E Principle, a tal “inteligência” nas bordas, eventualmente você terá problemas com ordem de mensagens e inconsistência de dados.
Isso pode acontecer com você agora ou em 10 anos, quem sabe 🤷♀️
Você precisa se preocupar? Diria que sim, mas implementar algo para resolver eh outra estória. Desenhar e implementar para tolerância a falhas tem custo e sua criticidade depende do seu contexto.
Links: