(relaxed beat)
- Welcome back to the Azure Cosmos DB Essentials series.
My name is Mustafa, and in this episode,
we're gonna cover consistency.
So, in NoSQL, availability, latency and throughput
are tied to the consistency of our database.
Because the constraints around maintaining related data
are relaxed in NoSQL, how we think
about consistent transactions needs a slight tweak.
Now, if a network connection is severed
in an acid compliant database, we will always
read the most recent committed transaction.
This holds true for Cosmos DB in the context
of a single logical partition, or basically
when it's not acting as a distributed database.
Now, because Cosmos DB is a distributed data platform,
we need to be able to address consistency
outside the context of a single logical partition.
To do that, we use five consistency models,
ranging from strong, which guarantees
we'll only read the most recent committed write,
kinda like acid, all the way to eventual,
which offers no consistency guarantees.
When understanding trade-offs around consistency,
we should understand that the consistency model
we choose will be determined by our application's needs
around availability, latency and throughput.
So, let's jump in.
The first and weakest consistency model
is eventual consistency.
With eventual consistency, there are zero guarantees
around when or in what order our data will be replicated.
Because there is no consistency guarantee,
eventual consistency provides the lowest latency
and the highest throughput of all the consistency models.
If our network connection is severed
and our write region needs to failover
from West U.S. to, say, East U.S.,
writes in the new region may conflict with existing writes
that weren't replicated from West U.S.
Since there are no guarantees that the most recent write
will be read at all, eventual consistency
is a great optimization tool for something
like real-time recommendation, where it doesn't matter
if the data is a few hours old, because it's unlikely
our preferences have changed from one hour to the next hour.
On the other side of the consistency models,
we have strong consistency.
In an online auction application that takes in bids
for rare collectible cards, it is crucial that we have
strong consistency to ensure that there's only one winner.
Now, in Cosmos DB, we define strong consistency
as our data being replicated by a majority quorum
in every region in which we are available.
If we have our data distributed across two Azure regions,
and we know within each region is replicated four times,
a majority quorum means that three out of four nodes
in each of the regions that were replicated
must confirm they have the most recent replica
for the strong guarantee to be met.
When using strong consistency, if the failover process
is initiated and our write region goes down,
Cosmos DB will hold up the write path
to ensure no conflicts emerge.
Now, in practice, this means that our bidders
would not see a winner as they kept refreshing their page.
Every read from any region returns the most recent write
to the dataset, and as a result, strong consistency
means lower throughput and higher latency
on the write path than eventual consistency.
In between these strong and eventual consistency models,
we have consistent prefix, session consistency
and bounded staleness.
With consistent prefix, the only guarantee we can give here
is that replication always happens in order.
So, if we make five writes to our database,
we'll replicate such that we'll see writes one through five
in that order, and one replica in the quorum
could have writes one, two, three,
another could have one, two, three, four,
but we'll never see a replica with only writes one and four.
If we've ever observed a group chat,
we've seen consistent prefix in action.
Every message received is in order of when it was sent.
If a new message was sent before it was received on my end,
it'll appear above my messages sent back into the chat.
We use consistent prefix when order matters, and pay
no latency cost since it's a single replica read path.
This guarantees low latency
and high throughput on the write path.
Session consistency guarantees that, within the context
of a single session, we'll always move forward in time.
In practice, this means that if I, as a user,
add something to my online shopping cart,
when I refresh my page, that item won't disappear
if it hasn't been replicated yet.
Upon refreshing the page, I am instead sent
to the most recent replica, so I'll always
be able to read my own writes.
Now, most of the time, session consistency
enjoys better latency and throughput
than bounded and strong consistency.
Session consistency would be used
for something like a wall post.
When I post on a friend's wall, if I refresh the page,
I don't want that post to disappear.
Otherwise, I'll post again, and all of a sudden,
my friend thinks I really, really wanna hang out.
Session consistency ensures this doesn't happen
and is the default consistency level
used by most Cosmos DB accounts.
With bounded staleness, we define a staleness window
in which the reeds are guaranteed
to honor the consistent prefix and can only be X number
of updates or T amount of time behind the most recent write.
Now, within that window, writes within a single region
are strong consistent, and writes from a different region
are consistent prefix, so guaranteed to be done in order.
Approaching the upper limit of that staleness window,
writes will be throttled so that replication can catch up,
resulting in low write latency
and high throughput most of the time.
Now, bounded staleness is ideal
for an application that needs low write latency
where write order matters, like in a mobile delivery app.
In this application, we wanna be able to take in
all orders submitted, so if writing to the first database
is throttled due to being too far
behind in the staleness window,
we don't wanna stop collecting orders.
Instead, we'll throttle new orders so that they
come in more slowly while our replication
catches up and the window shrinks.
That way, orders submitted while write is throttled
will still be fulfilled, they'll just be fulfilled
behind schedule, which is preferred
to those orders never being accepted at all.
Now, if we turn on multi-region write,
things change a little bit.
Outside of the strong consistency model,
multi-region write improves write latency,
but because with strong consistency, every write needs
to be replicated across every region anyway,
we may as well write from a single region.
So, in short, we cannot use strong consistency
and multi-region write together.
With eventual consistency, reads are still fast,
but writes get faster with multiple nodes writing.
Now, in all the other consistency levels, bounded staleness,
consistent prefix and session consistency,
writes within each writer's own region
are consistent prefix, and so recorded in order,
and all writes into a different region
are eventually consistent, meaning no guarantees.
So, I know that was a lot, but it's important
when working in Cosmos DB that we figure out
what the consistency needs of our application are,
and then consider whether multi-region write
is something we actually need to use in our application.
Thanks for joining us for this episode on consistency,
and join us in the next episode to talk about HTAP
and synapse link in Cosmos DB.