Microservices with Databases can be challenging...

Software Developer Diaries
6 May 202420:52

Summary

TLDRThis video explores the complexities of managing databases in a microservices architecture, highlighting anti-patterns like shared databases and advocating for separate databases per service. It delves into transaction management, introducing patterns like two-phase commits and the saga pattern, which help maintain consistency across distributed systems. The script also covers API composition, CQRS for scalability, and event sourcing for tracking changes, all while emphasizing the importance of proper documentation and design patterns in microservices.

Takeaways

  • 😀 Microservices offer numerous benefits, but managing storage and databases within a microservice architecture can be challenging.
  • 🔄 The video discusses anti-patterns, such as the shared database pattern, which reduces modularity and scalability and can lead to issues like deadlocks.
  • 🚫 Deadlocks occur when multiple transactions wait for resources locked by each other, causing operations to hang indefinitely.
  • 🌐 The video recommends using separate databases for each microservice to improve decoupling and avoid technical issues like deadlocks.
  • 🔄 Distributed transactions are complex in microservices architecture, and the two-phase commit protocol is introduced as a method to ensure consistency.
  • 🤔 The two-phase commit can be cumbersome with many microservices, leading to the introduction of the saga pattern, which handles transactions in an event-driven manner.
  • 🛑 The saga pattern involves message brokers and allows for rollbacks in case of transaction failures, but it requires implementing custom rollback functions.
  • 🔍 API composition is presented as a valid pattern where a parent service aggregates data from other services, simplifying querying processes.
  • 📈 To improve throughput, Command Query Responsibility Segregation (CQRS) is suggested, which separates read and write operations into different databases.
  • 📝 Event sourcing is highlighted as a pattern suitable for tracking all changes, especially useful for compliance reasons in certain industries like finance or government.
  • 📚 The video concludes with the use of an AI tool to generate documentation for microservices and databases, showcasing its capabilities for developers and architects.

Q & A

  • What are the benefits of using microservices architecture?

    -Microservices architecture brings benefits such as modularity, scalability, and isolation, allowing for easier scaling and management of different services.

  • Why is the shared database pattern considered an anti-pattern in microservices?

    -The shared database pattern is considered an anti-pattern because it loses the benefits of modularity and scalability. It can lead to issues like deadlocks and challenges in maintaining consistency and design across different teams.

  • What is a deadlock in the context of database management?

    -A deadlock occurs when two or more transactions are waiting for each other to release resources such as locks on database objects, resulting in none of the transactions being able to proceed.

  • How can separate databases for each microservice improve the architecture?

    -Separate databases for each microservice allow for better decoupling and easier scaling. They prevent issues like deadlocks from affecting multiple services and enable independent scaling of services and their databases.

  • What is a distributed transaction and how can it be challenging in microservices?

    -A distributed transaction involves multiple services updating different databases simultaneously. It's challenging in microservices because it requires ensuring atomicity and consistency across different services, which is not straightforward when using separate databases.

  • What is a two-phase commit and how does it help with distributed transactions?

    -A two-phase commit is a method to ensure consistency in distributed transactions. It involves a 'prepare' phase where services are asked to prepare for a commit, and a 'commit' phase where, if all services are ready, the transaction is committed across all services.

  • What is the Saga pattern and how does it differ from the two-phase commit?

    -The Saga pattern is an alternative to the two-phase commit for handling distributed transactions. It involves a series of local transactions where each transaction produces an event that triggers the next transaction. It allows for better handling of failures and rollbacks compared to the two-phase commit.

  • What is API composition and how is it used in microservices?

    -API composition is a pattern where a parent service aggregates data from other services by making separate API calls to each service. It simplifies querying data from multiple services and databases without the need for a shared database.

  • What is CQRS and how does it improve throughput?

    -CQRS stands for Command Query Responsibility Segregation. It separates read and write operations into different models, allowing for the scaling of read operations independently from writes, thus improving throughput.

  • What is event sourcing and why is it useful for tracking changes?

    -Event sourcing is a pattern where every change to the state of an application is stored as a sequence of events. It is useful for tracking changes because it maintains a log of all transactions, allowing for the reconstruction of past states and compliance with tracking requirements.

  • How can documentation tools like Erase AI assist in creating documentation for microservices?

    -Documentation tools like Erase AI can generate outlines and comprehensive documentation based on specified topics and requirements. They can help developers and architects by providing a structured overview of best practices, patterns, and anti-patterns related to microservices and databases.

Outlines

00:00

😀 Microservices and Database Challenges

This paragraph introduces the complexities of integrating databases within a microservices architecture. It highlights the benefits of microservices but points out the difficulties in managing shared databases. The speaker discusses anti-patterns, such as the shared database pattern, which can lead to loss of modularity and scalability. Deadlocks and transaction issues are also mentioned as common problems when multiple services interact with the same database. The importance of understanding eventual consistency and proper database coupling is emphasized.

05:00

🔄 Distributed Transactions and Patterns

The second paragraph delves into the challenges of handling distributed transactions across separate microservices databases. It explains the concept of a two-phase commit as a solution to ensure atomicity in transactions. The process involves a 'prepare' phase, where services are asked to prepare for a commit, followed by a 'commit' phase if all services are ready. The paragraph also introduces the saga pattern as an alternative for handling transactions in a more scalable and event-driven manner, which can be more complex but also more flexible for larger systems.

10:01

📚 API Composition and CQRS

This paragraph discusses API composition as a method to aggregate data from different microservices, which is a valid pattern for microservices architecture. It also introduces the concept of Command Query Responsibility Segregation (CQRS), which separates read and write operations to databases. The benefits of having separate databases for reads and writes are explained, such as improved scalability and throughput. The paragraph also touches on the challenges of maintaining consistency between read and write databases and the potential solutions, including immediate replication or using event sourcing.

15:01

🗂 Event Sourcing for Data Integrity

The fourth paragraph explores the event sourcing pattern, which is particularly useful for applications requiring a log of all changes for compliance or historical tracking. Event sourcing appends events to a database, allowing for a detailed history of transactions. The architecture implications of event sourcing are discussed, including the use of event logs like Kafka and the creation of a read database that can be updated with snapshots of the application state. The paragraph also mentions the complexity of implementing event sourcing and its suitability for specific use cases.

20:03

📝 Documentation with AI Assistance

The final paragraph showcases the use of AI for generating documentation, specifically for the topic of microservices and databases. The speaker uses the tool 'eraser' to create an outline for documentation that covers best practices, patterns, and anti-patterns related to microservices and databases. The AI tool is praised for its ability to generate comprehensive documentation tailored to developers and architects, and the speaker encourages viewers to try the tool for its efficiency and utility.

Mindmap

Keywords

💡Microservices

Microservices refer to a software architecture style where an application is composed of small, independent services that communicate over standard protocols and are designed to support continuous delivery and deployment. In the video, the theme revolves around the challenges and patterns related to microservices, particularly in the context of database management. The script discusses how to properly couple databases with microservices and the anti-patterns to avoid, such as shared databases, which can lead to issues like deadlocks.

💡Storage and Databases

Storage and databases are essential components of any software system, providing a place to store, manage, and retrieve data. The video script highlights the complexity that arises when integrating storage and databases within a microservice architecture, emphasizing the need for proper design patterns to ensure scalability and isolation.

💡Design Patterns

Design patterns in software engineering are reusable solutions to common problems in a certain context. The script introduces various design patterns for managing databases in a microservice architecture, such as using separate databases for each microservice to enhance modularity and scalability, and the Saga pattern for handling distributed transactions.

💡Anti-Patterns

Anti-patterns are common responses to recurring problems that are usually ineffective and/or counterproductive. In the context of the video, the shared database pattern is described as an anti-pattern because it undermines the benefits of microservices, such as modularity and the ability to scale individual services independently.

💡Eventual Consistency

Eventual consistency is a consistency model used in distributed systems that guarantees that if no new updates are made to a given data item, eventually all accesses will return the last updated value. The video mentions eventual consistency as an important concept when discussing how to handle data across different microservices without relying on a single source of truth.

💡Deadlocks

A deadlock in database management occurs when two or more transactions are unable to proceed because each is waiting for the other to release resources. The script uses the concept of deadlocks to illustrate the problems that can arise when multiple microservices interact with a shared database, leading to resource contention and system stalls.

💡Distributed Transactions

Distributed transactions involve multiple database systems that must be updated atomically to maintain data integrity across the systems. The video discusses the challenges of managing distributed transactions in a microservice architecture, introducing solutions like the two-phase commit protocol and the Saga pattern.

💡Two-Phase Commit

The two-phase commit is a type of atomic commitment protocol in which a transaction involving multiple nodes is committed only if all nodes confirm that they can successfully complete the transaction. The script explains how this protocol can be used to ensure consistency in distributed transactions across microservices, despite the complexity it introduces.

💡Saga Pattern

The Saga pattern is a sequence of local transactions where each transaction updates data within a single service, and if any transaction fails, compensating transactions will revert the changes. The video describes the Saga pattern as a way to handle complex distributed transactions in a microservice architecture by using a series of events and local transactions.

💡API Composition

API composition is the process of combining multiple web APIs to create a new API that provides additional functionality. In the video, API composition is presented as a pattern where a service aggregates data from other services, allowing for a more flexible and scalable approach to data integration in a microservice architecture.

💡CQRS

CQRS stands for Command Query Responsibility Segregation, a pattern that separates read and write operations for a database. The video discusses CQRS as a method to improve throughput and scalability by having separate databases for reading and writing, which can be scaled independently based on demand.

💡Event Sourcing

Event sourcing is a method of persisting the state of a business entity as a sequence of events. The video introduces event sourcing as a pattern that can be used to maintain a log of all changes made to an entity, which is particularly useful for compliance and auditing purposes, as it allows for tracking the history of data changes.

Highlights

Microservices offer numerous benefits, but managing storage and databases within a microservice architecture can be complex.

Different design patterns exist for coupling databases with microservices, including anti-patterns to avoid.

The 'shared database' pattern is an anti-pattern, leading to loss of modularity, scalability, and potential deadlocks.

Using separate databases for each microservice improves decoupling and scalability, avoiding technical issues like deadlocks.

Distributed transactions in microservices require special handling, such as the two-phase commit protocol to ensure atomicity.

The saga pattern is an alternative for handling transactions across multiple microservices, using a series of local transactions.

API composition is a method for aggregating data from multiple services, which is a valid approach in microservices architecture.

Command Query Responsibility Segregation (CQRS) separates read and write operations to databases, improving throughput.

Event sourcing is a pattern that logs every change as an event, useful for tracking and compliance in certain domains.

The use of a message broker in the saga pattern facilitates coordination between microservices during transactions.

Automatic replication from a write database to read databases can be set up to ensure data consistency with less immediate overhead.

Rollbacks in the saga pattern require custom implementation, adding overhead but ensuring transaction consistency.

Materialized views can be used to read data from a database, updating periodically from event logs.

Eraser.io is highlighted as a tool for creating and modifying AI-generated diagrams for microservices architecture.

The video also demonstrates using Eraser.io to generate documentation outlines for microservices and databases.

Documentation is crucial for developers and architects to understand best practices and patterns in microservices.

The video concludes by showcasing the generated documentation outline, emphasizing the utility of Eraser.io's AI features.

Transcripts

play00:00

microservices bring a lot of benefits

play00:02

there's no doubt about that but at the

play00:04

same time it gets kind of tricky when

play00:06

you're trying to deal with storage and

play00:08

databases within your microservice

play00:10

architecture because the question is how

play00:12

do you actually properly couple them

play00:14

together well turns out there are

play00:16

different design patterns for that that

play00:18

we're going to learn in this video and

play00:20

to start with some anti- patterns

play00:22

meaning how not to do that and of course

play00:24

we're going to learn very important

play00:26

things such as eventual consistency

play00:28

Deadlocks transactions and so on over

play00:30

the course of this video so if you're

play00:32

ready buckle up and let's get started

play00:36

all right folks so we're going to start

play00:37

with the very first pattern or rather an

play00:39

anti- pattern and I'm going to explain

play00:41

why which is called shared database

play00:44

pattern and I'm going to use erasers AI

play00:46

diagrams here to save time because I'm

play00:49

lazy and I'm simply going to tell it

play00:51

that it's a cloud architecture and paste

play00:53

this text so I'm going to create two

play00:55

microservices payment and user services

play00:58

that are is to instances that to the

play01:00

same shared database separately let's

play01:02

click generate and let the AI do its

play01:05

thing so as you can see we have a shared

play01:08

database and our services are talking to

play01:11

it separately now why is this considered

play01:14

an anti pattern well we're losing one of

play01:17

the best features of microservices which

play01:19

is modularity and scalability and or you

play01:22

can say isolation instead of modularity

play01:25

so usually whenever you have a separate

play01:27

database attached to your service you

play01:29

can scale much easily you can simply

play01:31

create new instances automatically which

play01:34

is autoscaling but in this case we're

play01:36

bound to the same database so apart from

play01:38

the human problems or human aspect which

play01:41

is two teams trying to manage the same

play01:44

database and which is going to lead to

play01:46

worse consistency and design because

play01:49

yeah maybe sometimes it's not that easy

play01:51

to align with different teams on how to

play01:53

design your database but apart from that

play01:56

working on the same database with

play01:58

different microservices can actually

play02:00

introduce technical issues as well for

play02:02

example Deadlocks what's a deadlock

play02:05

let's read about it in a database

play02:07

management system a deadlock occurs when

play02:09

two or more transactions are waiting for

play02:11

each other to release resources such as

play02:14

locks on database objects that they need

play02:16

to complete their operation as a result

play02:18

none of the transactions can prede

play02:20

leading to a situation when they are

play02:22

stuck or deadlocked so basically when a

play02:25

payment service tries to make like a big

play02:27

update on the database it's going to

play02:29

lock the table so that there's no other

play02:31

service that kind of modifies this data

play02:33

while the update is happening which can

play02:35

lead to data in inconsistency or loss

play02:38

that's why it's going to lock this table

play02:40

and then at the same time user service

play02:42

tries to update this table and it fails

play02:45

because the database or the database

play02:47

table is under a deadlock so as you can

play02:49

see there are many reasons why not to

play02:51

use a shared database for your

play02:53

microservice of course you can go with

play02:55

this if you have a smaller application

play02:57

and not that much load on your plat

play02:59

platform but if you're trying to scale

play03:01

in the future definitely don't use

play03:03

shared database all right instead what

play03:06

you can do is the following so let's

play03:08

clean this up a bit I'm going to move

play03:10

this here and I'm going to remove my

play03:13

lines and arrows so what we can do is

play03:16

actually eraser allows us to modify this

play03:20

AI architecture or or use this AI tool

play03:23

to modify our diagram by simply editing

play03:26

a prompt so I'm going to say now use a

play03:29

separate database for each micro service

play03:33

and let's see what it's going to

play03:37

do all right it recreated the diagram

play03:40

and it created separate databases I'm

play03:43

somehow getting fascinated by how smart

play03:45

the AI is when drawing diagrams so now

play03:48

this is a better pattern because we can

play03:50

scale separately so we can scale the

play03:53

this service and a database separately

play03:55

now it's probably not depicted here but

play03:58

payment service and payment database are

play04:00

going to be living in separate Docker

play04:01

containers so usually it's not a good

play04:03

practice to pack them all together

play04:05

within one Docker container but if aside

play04:08

from that now we have better decoupling

play04:10

so the requests coming here are going to

play04:13

take their own time even if this

play04:15

database gets deadlocked deadlocked

play04:17

there's no issue that user service is

play04:20

going to suffer from this all right this

play04:22

is a better architecture when you're

play04:24

trying to deal with microservices now

play04:26

there are some things called

play04:28

transactions as you can see this diagram

play04:31

is kind of cool we have separation but

play04:33

how do we actually deal with

play04:35

transactions so let's say we have

play04:37

another service so let's modify and say

play04:40

order service is going to call both

play04:45

payment and user service so let's

play04:48

generate another service that's going to

play04:50

connect to our two services like this

play04:53

now imagine this diagram order service

play04:55

wants to update the payment information

play04:58

and the user information at at the same

play05:00

time this is called a distributed

play05:02

transaction now how do we deal with

play05:04

distributed transaction because if we

play05:06

were having a shared database we could

play05:08

easily do a transaction within one

play05:11

shared database and maybe lock it of

play05:13

course which introduces a problem but

play05:15

now we cannot the order service cannot

play05:18

simply do a transaction saying ay user

play05:21

service do your thing and at the same

play05:23

time payment service do your thing and

play05:25

we're just safe all right because what

play05:27

if this transaction that is Atomic so

play05:30

follows the asset principle the

play05:33

atomicity means that whatever started

play05:35

can be rolled back all right so if we're

play05:38

trying to assure that both of these

play05:40

databases are going to be eventually

play05:42

updated what if one of them actually

play05:44

errors out and but user service proceeds

play05:46

so the user database is going to be

play05:48

updated but the payment information is

play05:50

going to be old so we don't want that

play05:52

but how can you ensure this when you're

play05:54

having microservices this is one of the

play05:56

issues that comes up whenever we Dr deal

play05:59

with with distributed transactions and

play06:01

there is one work around for this called

play06:03

a two-phase commit what a two-phase

play06:06

commit means is that we're going to have

play06:09

two phases in order to ensure

play06:11

consistency within our transaction all

play06:13

right so what this going to look like is

play06:16

the order Service First is going to

play06:17

issue a uh one phase which is called

play06:21

prepare so it's going to tell user

play06:23

service hey guys prepare for an up

play06:26

database update and the payment services

play06:28

are going to start a transaction to

play06:31

begin so if we look here I'm looking at

play06:34

pogress so pogress lets you do

play06:36

transactions in the database like this

play06:38

so you can start with a begin query and

play06:40

then you can Define your query and then

play06:42

before doing an in or you can Define

play06:45

your query with an insert and then

play06:47

committing is already the second phase

play06:49

that we're talking about all right so

play06:51

before committing if there are no errors

play06:53

happen until this point this payment

play06:55

service can tell back to the order

play06:57

service that hey everything is looking

play06:59

good there are no errors there are no

play07:00

Deadlocks so I can actually commit as

play07:03

soon as the order service knows that the

play07:05

user service and payment service are

play07:06

ready to commit IT issues the second

play07:09

phase which is the actual commit phase

play07:11

and then the second phase lets the user

play07:14

service and payment service know that

play07:16

hey you have had these you already have

play07:18

these queries ready just commit them all

play07:20

right we're going to commit them and

play07:22

everything is good but if one of them

play07:24

fails the user service says hey I'm not

play07:27

ready to commit so what we're going to

play07:29

do do is we're going to roll back

play07:31

meaning we're going to close this

play07:32

transaction okay how cool is that so

play07:35

this is one of the ways of dealing with

play07:38

distributed transactions but there's one

play07:40

problem so in our use case we have only

play07:42

two microservices what happens if we

play07:44

have 10 other microservices that the

play07:46

user service is talking to so imagine we

play07:48

have another inventory service we have

play07:50

another I don't know customer service

play07:52

and so on it's very hard to orchestrate

play07:55

all of that so order service is going to

play07:57

issue kind of first phase to all of them

play07:59

and then it's basically going to be a

play08:01

mess until you wait for the second phase

play08:03

that's why people came up with another

play08:06

pattern called a saga pattern so I'm not

play08:08

talking about Harry Potter or Star Wars

play08:10

but it's literally called Saga pattern

play08:13

kind of means that these transactions

play08:15

are going to be relate to each other so

play08:17

for this I'm actually going to create

play08:20

some microservices let's say this one is

play08:22

order and this one is payment this one

play08:26

is going to be user so we're going to up

play08:29

update data in all of those databases

play08:32

and that's one is going to be inventory

play08:34

all right so user and inventory and they

play08:37

of course have their respective

play08:38

databases so let's take a database here

play08:42

and place a database for all of them

play08:44

here so they're going to be living in

play08:46

the bottom of these services and here

play08:49

and here so the Saga pattern is going to

play08:51

look the following way and this is by

play08:53

the way our second pattern that we can

play08:56

use so the S pattern is going to have a

play08:58

message br broker so something that we

play09:00

already covered in one of our previous

play09:02

videos this can be a rabbit mq all right

play09:05

so we're going to have a broker such as

play09:07

rabit m q and this is our broker so

play09:11

what's going to happen is the order

play09:12

service is going to issue an event that

play09:15

hey I need to update something to the

play09:17

message broker the payment service is

play09:19

subscribed to this it's going to pick it

play09:21

up and as soon as it's processed it's

play09:23

going to issue another event that the

play09:24

payment has been processed then the user

play09:26

picks it up and then the user issues

play09:28

another event that's it's done updating

play09:30

its database here and then eventually

play09:33

the inventory picks it up and updates

play09:35

its database here so as you can see all

play09:37

of them are updating their databases one

play09:39

after another and they're doing this in

play09:41

an event driven fashion so how do we

play09:44

deal with rollbacks then well the

play09:45

rollbacks are going to work the

play09:47

following way if this one fails if the

play09:49

payment fails then of course user and

play09:51

inventory are not going to be able to

play09:53

update their databases which is good for

play09:55

us but we can also roll back the order

play09:58

updates so the update on the database is

play10:00

going to be rolled back but not so fast

play10:03

because it's not so easy to implement

play10:05

that this literally means that you need

play10:06

to implement all of those roll back

play10:08

functions yourself so there's some

play10:10

overhead additional overhead is not

play10:12

always good but this is one way of

play10:14

ensuring an actual um distributed

play10:17

transaction consistency all right and

play10:19

this is the second pattern that you can

play10:21

do with your databases basically use

play10:23

Saga pattern just keep in mind that it

play10:26

can get a bit complicated all right so

play10:28

far we implemented two or looked into

play10:30

two different patterns the shared

play10:33

database which is an anti- pattern so

play10:35

we're not talking about that the

play10:36

separate databases and Saga pattern now

play10:39

there's another one which is called a

play10:41

composition so let's take our diagram

play10:44

here to make it clean so whenever we're

play10:47

looking at this one actually so this is

play10:49

already called a composition so let's

play10:51

change the title of this that we can

play10:53

easily do so API composition and you

play10:56

might be asking what does it actually

play10:58

mean so we are apparently already using

play11:01

API composition which is if we have two

play11:03

Services here payment service and user

play11:05

service and we need to query data from

play11:07

or their respective databases it's quite

play11:10

easy so quering is much easier than

play11:12

updating what we're going to do is we

play11:14

simply going to have an order service

play11:16

that can query payment service first of

play11:18

all and then it can query the user

play11:20

service and then wait for the events to

play11:23

finish and then simply aggregate all the

play11:26

results here in the order service okay

play11:28

so it's called an event or or API

play11:31

composition meaning you can always have

play11:33

a parent service that tries to aggregate

play11:36

data from other services and this is

play11:38

totally fine this is not a antip all

play11:40

right so going further what can we

play11:43

actually do in order to improve our

play11:46

throughput so to say all right so let's

play11:48

say we don't have the order service

play11:50

anymore or let's say we have the order

play11:52

service but no other services so I'm

play11:54

going to remove to other services and as

play11:56

you can see this is super easy with

play11:58

eraser .io and let's keep the database

play12:02

maybe but call it order database and we

play12:05

are going to connect the order service

play12:08

to order database like this and we're

play12:10

going to delete the other connection all

play12:12

right so like this so what we're having

play12:16

here is that the order service is going

play12:18

to talk to the order database but

play12:21

whenever we're dealing with a lot of

play12:22

data it's actually a good practice to

play12:24

separate your view database meaning

play12:27

whenever you're doing uh select compar

play12:29

to your update so what we're going to do

play12:31

is we're going to create another

play12:33

database like this so we're going to say

play12:36

order view database and the second one

play12:39

is going to be order write or rather not

play12:42

view but read all right so we have now

play12:45

two databases and what we can do is

play12:47

probably delete this and we're going to

play12:49

say order service reads from order read

play12:53

database and it's also going to connect

play12:55

to order write database oops so order

play12:58

ser is connected to order the right

play13:00

database so whenever we're reading the

play13:03

information we're going to read it from

play13:05

here and whenever we write we're going

play13:07

to write it here and as reads happen

play13:11

more often than wres we can separately

play13:14

scale this database many times so we can

play13:16

literally take this database and scale

play13:19

it one time and two times all right now

play13:22

we have more throughput whenever we try

play13:24

to read the information from our API

play13:27

which is cool and this is called CQ Q RS

play13:30

so command query responsibility

play13:33

segregation because we're dividing the

play13:35

responsibility between our reads and

play13:37

writes and now you might ask but how do

play13:39

we actually ensure consistency well

play13:41

there are separate ways all right so

play13:43

whenever you were writing to the order

play13:45

database what we can do is at the same

play13:48

time write to all of our read databases

play13:51

as you can see this is probably not

play13:52

efficient because we need to make sure

play13:54

that we ritee right to all the replicas

play13:57

so this is a bit of a overhead but we

play13:59

can also kind of make sure that there's

play14:01

an automatic replication from write to

play14:04

read database it's going to happen

play14:06

within a millisecond probably so there's

play14:08

an automatic script that can do every

play14:11

time you write to the right database

play14:13

it's going to update the read databases

play14:16

as well but as you notice this is also

play14:19

might not be perfect in some cases why

play14:22

because if the updates of your database

play14:25

are not that critical so if the fact

play14:28

that as soon as the right database is

play14:29

updated updating your read databases at

play14:32

the same time within the same second is

play14:34

not crucial maybe there's something else

play14:36

that we can use because otherwise

play14:38

updating all the read databases as soon

play14:40

as the right database has been updated

play14:42

also adds some load to your server okay

play14:45

otherwise this is quite legit but if our

play14:49

if the time is not so critical for

play14:51

example imagine an eCommerce website

play14:54

where users are updating their shopping

play14:56

cart and it's not so critical to update

play14:59

the shopping cart of a user as soon as

play15:00

the user clicks on plus but you know one

play15:03

or two seconds of delay is totally fine

play15:05

maybe we shouldn't be updating our read

play15:08

databases so quickly but what what we

play15:10

can do instead is use a an event

play15:12

sourcing pattern so what is an event

play15:14

sourcing pattern event sourcing pattern

play15:16

is especially good in some of the use

play15:18

cases such as finances I'm not talking

play15:21

about stock market because stock market

play15:23

needs realtime updates but finances like

play15:26

Banks where you want to see all of your

play15:29

transactions in the past so we're going

play15:31

to keep literally the log of every

play15:33

transaction or some other governmental

play15:36

organizations there can be many use

play15:38

cases so what is the difference so let's

play15:41

create a

play15:43

diagram and this one is going to be an

play15:46

entity relationship so let's say create

play15:48

a a user table with three different

play15:52

users as rows okay I changed it to ID

play15:55

name and surname and let's generate it

play15:58

now

play16:00

and we're going to get a database with

play16:03

three different uh rows all right so

play16:06

whenever we update our user let's say we

play16:09

want to update it surname or name the

play16:12

update is in place meaning we're losing

play16:15

the track of the old name but what if

play16:17

for compliance reasons we wanted to see

play16:19

their older name as well maybe we are

play16:21

some kind of a governmental crucial

play16:23

organization that need to track all the

play16:26

changes within the system well that's

play16:27

why you can use an event sourcing system

play16:30

all right so event sourcing is something

play16:32

that's going to basically append events

play16:35

to to to the database so one event which

play16:38

was create user and there's some

play16:41

Associated data with this another one

play16:43

was update user so we are already going

play16:47

to be able to find the information when

play16:49

the user was created so maybe the name

play16:51

was Tim and then later it got updated to

play16:53

John so if we go back into the events

play16:55

and see that whenever the user was

play16:57

created it was Tim can easily track this

play17:00

back so it's not that easy to do it with

play17:02

traditional databases that's why it's

play17:03

good to have an event log so how is this

play17:05

going to look within the architecture of

play17:08

your database so let's say you have a

play17:09

service backend service and it's going

play17:12

to or let's say it's actually a user

play17:14

service so like this it's going to

play17:15

update or connect to an event log and

play17:19

event log can be actually kka stream and

play17:22

we're going to write all the logs in

play17:24

here such as oops let's remove that such

play17:27

as update user and then again update

play17:29

user then maybe we want to want to

play17:32

delete the user so if if we if our

play17:35

business requires to uh save all these

play17:38

changes within our database we can save

play17:40

them within the cka stream and they can

play17:42

be stored there as long as possible all

play17:45

right so here's our first connection but

play17:47

what happens if we want to read that

play17:49

data all right this is very very tricky

play17:52

So reading the data will be from an

play17:54

actual database all right so we're going

play17:56

to have another DB here and this is

play17:59

going to be a read DB so what happens is

play18:02

we can have changes on this kavka stream

play18:05

and every time a change happens we kind

play18:07

of stream it to our read database so

play18:10

whenever there's another service maybe

play18:12

it can be a user service or some other

play18:14

service we want to read the data we're

play18:16

going to read it from a materialized

play18:18

view so first of all the question is how

play18:20

do we update the read database at the

play18:23

same time well you can actually listen

play18:25

to different events all right not only

play18:27

in mongodb collection you can listen to

play18:29

different events triggers in my SQL all

play18:32

right you have triggers meaning it kind

play18:35

of listens for events but you also have

play18:37

the same similar thing in Kafka so as

play18:40

soon as the event happens we can stream

play18:41

it to a database all right we're going

play18:43

to look into the code and then actual

play18:45

implementation in the future video but

play18:46

for now just keep in mind this concept

play18:48

okay so we have a read database and the

play18:50

read database is basically going to take

play18:53

all the snapshots that happened in

play18:55

between so it's not going to store all

play18:57

the events because otherwise it would be

play18:59

replication but it's going to save all

play19:01

the snapshots meaning the states of the

play19:03

application at a certain point of time

play19:06

okay one more last thing that I want to

play19:07

show you is actually something that has

play19:10

to do with documentation and razor

play19:13

actually we have this tab called

play19:14

document and eraser recently they

play19:17

actually let me know that we can now use

play19:18

their AI features fully because it's so

play19:21

great as you saw we can actually even

play19:22

generate documentation here so as you

play19:25

know we talked about microservices and

play19:27

databases so I can click on generate

play19:29

outline and I can kind of create

play19:31

documentation for our video so I'm going

play19:34

to say create a document that talks

play19:38

about micr

play19:40

services and databases with their

play19:44

different best practices and pattern

play19:47

also include the anti patterns and let's

play19:51

say what it generates so the technology

play19:53

stack I'm going to say SQL I'm going to

play19:56

say Kafka and so on so let's click

play19:59

generate what is the desired level of

play20:00

detail for now it's just an overview

play20:03

what's the primary goal of the document

play20:05

to offer to private a comprehensive

play20:07

overview what's the intended audience

play20:09

let's say developers and Architects what

play20:11

aspects of SQL in relation to micros

play20:14

service should be covered best practice

play20:15

basically it's going to ask you

play20:17

different questions that you can specify

play20:19

and then it's going to generate this

play20:21

document so let's click on generate and

play20:24

now our documentation is going to be

play20:25

generated basically I even could have

play20:28

used this to go as an outline for our

play20:31

video how cool is that so guys give it a

play20:33

try eraser is amazing and they're

play20:35

actually my friends that I'm also in

play20:37

contact with and I've been enjoying this

play20:40

application since then so this was it if

play20:42

you enjoyed the video always as always

play20:45

give us a thumbs up and I'm going to see

play20:46

you guys in the next video goodbye

Rate This

5.0 / 5 (0 votes)

Related Tags
MicroservicesDatabasesArchitectureDesign PatternsAnti-PatternsEventual ConsistencyDeadlocksTransactionsDistributed SystemsAPI CompositionCQRSEvent SourcingKafkaSQLDevelopersArchitectsTech TutorialCloud ArchitectureSoftware ScalabilityData Management