Reputation: 50
I'm learning about microservices but maybe I'm studying it wrong. My environment is on premisses, which makes my scenario a little different. When thinking about monoliths, we do a transaction over all tables we need. If something goes wrong, don't commit to the database and everything is ok.
But now, thinking about microservices, what if I have a service (stock) to take care of my supplies? And another service (sales) to take care of sales. When a sale is committed, I need to decrease my stock.
Can anyone please, give me a hand with where should I start about it?
Upvotes: 0
Views: 699
Reputation: 1082
in distributed system the data consistency during transaction among independent services is always a challenge. one business process distributed to independent units or services which are anonymous to each other and all should work okay to finish the job successfully and case of failure the process should rollback or recover or not commit what ever strategy necessary should take place. you have two options of
read 2PC vs SAGA
read SAGA
most saga implementations contain StatemMachine unit and Steps/Activities. the the state machine will orchestrate/coordinate the steps in the transaction or process and for each steps (eg persist A to A_DB then Persist B to B_DB...) there is implementation for Compensate in case if any step face the failure it will trigger the compensation of its previous steps and so on. you may rollback or do any thing you want there. All this together forms a routing Slip for a transaction over services.
base on your profile you have .net in your stack. you can use Masstransit i like that.
read Masstransit SAGA State machine
read Courier routing slip. help you to implement routing Slip
watch Chris patterson serries its awsome.
Another approach you have to consider is Event sourcing Pattern and you always hear that with CQRS.this pattern help you in events projection for an business logic and persist them in append only DB along side actual DB in the service and Update the status of particular events projection.
Upvotes: 2
Reputation: 1740
Let me put a bold statement out there: don't use transactions across microservices.
Transactions work amazingly in a single node application, like a relational database. They are quite complicated when stuff gets distributed.
The complexity comes from all edge cases a distributed system needs to handle. When a node or a microservice goes offline (or disconnects from the rest of the network) the system as whole needs to decide on what to do next. More or less there are two options - sacrifice correctness or availability. This is what CAP theorem is about.
Putting transactions aside, I recommend to do a two step process: first the sales service reserves an item and then the service confirms a purchase.
It makes sense to pay attention to failure scenarios: for example, what will happen if an item got reserved, but never purchased or cancelled - because the sales process failed.
It seems that a timeout would be a good idea - if an item is not updated (purchased or cancelled) in a given interval, then assume it is cancelled. This is a dangerous path to take. It is a total possibility, that the sales process if frozen and it may unfreeze after the timeout. This will put your system in an inconsistent state - an item might be sold twice.
A better approach would be a service which will check for reserved items and do extra steps to make sure it is safe to release them. It does not has to be a dedicated service, maybe a process in an existing one.
In either case, with the correctness being the goal - we absolutely don't want to double sell items - your system will sacrifice some availability. But having the clean up process as a dedicated flow, will minimize the availability hit.
Upvotes: 1