In Natural Intelligence we have built a Micro services architecture (MSA), that kind of architecture creates many services that runs independently. This pattern takes SOA benefits but keeps it simple and useable. That is why MSA has many benefits, and the one which stands out the most is making deployment easier (independently services).
However, MSA had some disadvantages, one of them is lack of ability to use transaction between services (XA-transaction). In this case the best practice is to hope for ‘eventual consistency’, which means do your logical transaction and hope it will work out at the end… not good enough for us.
The problem we had to deal with is to generate a version in all of the services (a kind of entities snapshot among several services) that acts as a transaction. In other words, we had to make sure all services create a new version successfully or gracefully rollback to the old one. As you can figure out, distributed transaction is not an easy mission with MSA.
Our solution is based on 2-phase commit protocol with a tweak.
The phases are:
- Validate the changes.
- Commit the changes.
- (If necessary) rollback to the old version.
We made a service that is responsible to all transactions between services.
First, the service makes sure that each service which needs to commit can run the command (Validation stage). When all services answer positive for validation, we know the option of applicative error is reduced, and therefore rollback possibility is reduced as well.
Second, we ask for each service to commit seriality. We continue to the next element only if the last one finishes successfully. In case of a failure we stop and run rollback from the current action back to the start.
- Transaction in MSA is difficult to manage.
- Our solution is based on 2-phase commit protocol.
- We create transaction-manager service that manages the current transaction.
- Each transactional service has to have 3 endpoint in their API:
- When all services are done with the validation stage, it can continue to the commit/rollback stage.
- If one of the services fail, we stop the commits and run rollback back to the start.