Posted by Abhishek on December 11, 2019
In the previous blog of “Understanding Microservices Architecture – Part 1“, we did a detailed study about monolithic v/s microservices architecture, the benefits and drawbacks of each architecture and the solution approaches to it. I highly recommend you to read the “Understanding Microservices Architecture – Part 1” blog before diving into this blog as it would help you connect to the context of what we are going to learn here. Well, we understood that Microservices Architecture is the way forward. Now, here comes a lots of questions in our mind.
The solution here is to adopt EVENT BASED approach into microservices to solve the interaction issues. With respect to data management, we can either choose “Shared Database” approach or “Database per service” approach. With “Shared Database” approach, you have 1 single database with many tables in it. Different services might talk to one of more tables. This is pretty simple to achieve and ACID principles help maintain data consistency. But the biggest problem with this approach is that individual services have tight coupling with the database. This means that if we design a set of microservices, then every microservices would have to talk to this single database. If a team working on order service decides to update the database schema, then they have to go and talk to other service team and figure out if this schema update will break their service or not. Thus, things slow down and team start losing their autonomy/independent nature. As autonomy degrades, sticking to agile model becomes painful. The recommended approach in Microservices is for each service to have its own database. Therefore, each service gets it own private database which has all the information for that service to operate. For example, Order Service has an Order Database, Customer Service has a Customer Database and so on. This ensures Loose Coupling. But it’s more complex to get this working from a TRANSACTIONAL scope. Right? Now, we get confused on how a TRANSACTION is defined in Microservices Architecture because different services with their own database have to communicate and co-ordinate for completing a business transaction. The solution to this TRANSACTIONAL confusion is to adopt EVENT DRIVEN ARCHITECTURE. This means that when something significant happens in a service, that service has to raise an event. This event can be observed by other services and act upon that. With this, you can achieve eventual consistency in a transaction. For example, when a customer places an order, the following actions takes place.
Here, we have 3 ACID transactions happening on each service and finally contributes to ACID of the entire order transaction becoming consistent. When we say “EMIT AN EVENT”, the question arises
The way to tackle this problem is by using “EVENT SOURCING” technique. In this technique, a separate table for Event is maintained where the Id, type of event, event data are all stored. Publisher services write event records to this table. Subscriber services read the event records from this table based on Event Type and carry out their actions. A benefit of Event Sourcing is that the entire history of a transaction from start till end can be traced from this Event Table.
If there is a need to replay/retry from a particular step, you can do that easily because every step/event of the entire transaction was recorded with its data. Benefits of Event Sourcing
That was a lot of learning. Isn’t it? In the Part 3, we will understand the querying complexities involved in Microservices and how we can solve this problem.