FacebookLinkedInShare

Intro

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.

 

Motivation

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.

 

NI solution

Our solution is based on 2-phase commit protocol with a tweak.

Screen Shot 2015-03-21 at 8.39.57 PM 

The phases are:

  1. Validate the changes.
  2. Commit the changes.
  3. (If necessary) rollback to the old version.

Explanation

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.

TL;DR

  • 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:
    • Validation
    • Commit
    • Rollback
  • 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.
  • Ant Kutschera

    Hi Shai, You haven’t described exactly how you implemented the solution. Is it safe to assume that you had to write some code which works as the transaction manager? I have faced the same challenges, but for me writing such code is not an optimum solution – there are frameworks available to solve these problems, such as the Atomikos Transaction Manager or https://github.com/maxant/genericconnector (I am the author).

  • Vlad Lyga

    Why not use eventual consistency and events to synchronize state?