Azure Cosmos DB is a globally distributed database service that provides us as developers with well-defined levels of consistency. With distributed databases, we as developers are usually limited between two extreme levels of consistency: eventual and strong. In Azure Cosmos DB, this is not the case.
Cosmos DB provides 5 levels of consistency rather than just 2 extremes. Each level comes with availability and performance trade-offs, but having these levels of consistency to choose from provides developers with more flexibility when it comes to making their Cosmos DB applications available and performant enough for their requirements.
The below diagram shows the 5 levels of consistency that Cosmos DB provides. We’ll cover each one in more detail in a bit.
Consistency Levels in more detail
- Strong : Reads are guaranteed to read the most recent committed version of an item. Clients will never see a partial write or an uncommitted write. We are always going to be able to read the latest committed write when our consistency level is set to Strong
- Bounded staleness : Reads might lag behind writes behind at most K updates of an item or by T time interval. We can configure bounded staleness in by either the number of versions of the item or by time interval.
- Session : Within a single session, reads are guaranteed to honor consistent-prefix, monotonic reads and writes, read-your-writes and write-follow-reads guarantees. Clients that are outside the session that are doing writes will be eventually consistent.
- Consistent prefix : Any update that is returned will contain some prefix of all the updates. Reads in consistent prefix are guaranteed to never see writes that are out-of-order
- Eventual : In eventual consistency, there’s no ordering guarantee on reads. Replicas of writes across multiple write regions will eventually merge across all regions.
Which Consistency Level is right for me?
Depending on what API your Cosmos DB account is using, the level of consistency that you need will vary depending on the needs for your application. The Azure Docs provide some great guidelines for determining which consistency level will work for your application:
Choose the right consistency level for your Azure Cosmos DB app
TLDR, generally you should set the consistency level on your Cosmos DB account a level stronger than your actual needs. However, if you need high availability and low latency, you should set the consistency level to eventual consistency.
Setting the Consistency Level in your Cosmos DB account
We can configure the default consistency level that our clients use in a variety of ways.
In the portal, we can easily do this by clicking on the default consistency option underneath settings:
Once we’re here, we can select the level of consistency that we want and clicking save. The Cosmos DB team has also created a neat little visualization of musical notes that helps explain the levels of consistency.
If you’re provisioning Cosmos DB accounts using Terraform, you can define the consistency level like so:
consistency\_policy {
consistency\_level **=**"BoundedStaleness"
max\_interval\_in\_seconds **=** 10
max\_staleness\_prefix **=** 200
}
In this example, the consistency_level defines…well, the consistency level (obvious enough). The max_interval_in_seconds setting represents the amount of staleness in seconds. You can set this between 5 seconds and 86400 seconds (1 day). You’ll need to specify this value if you’re setting the consistency level to Bounded Staleness. The max_staleness_prefix value represents the amount of stale requests that you will tolerated. Again this is required for Bounded Staleness and the range of requests can be set between 10 to 2147483647.
You can also set the default consistency level using AZ CLI or PowerShell. Check out how you can do it here:
Manage consistency in Azure Cosmos DB
Should our clients need to, we can override the default consistency level that we set for our Cosmos DB accounts per request. This is overridden at the account level. For example, in the V3 .NET SDK, we would do this like so:
Container container = client.GetContainer(databaseName, collectionName);
ItemResponse<SalesOrder> response = await container.CreateItemAsync<SalesOrder>(salesOrder);
string sessionToken = response.Headers.Session;
ItemRequestOptions options = new ItemRequestOptions();
options.SessionToken = sessionToken;
ItemResponse<SalesOrder> response = await container.ReadItemAsync<SalesOrder>(salesOrder.Id, new PartitionKey(salesOrder.PartitionKey), options);
Can we customize the consistency level for reads and writes?
Yes you can! If you to control the level of data durability in your application without harming the availability of it, we can use custom synchronization in our applications to control the level of durability that we need.
Let’s see how we can do this using the V3 .NET SDK. First, we would need to set up two clients for our custom synchronization for both read and write operations:
class MyDataAccessLayer
{
private CosmosClient writeClient;
private CosmosClient readClient;
public void InitializeAsync(string accountEndpoint, string key)
{
CosmosClientOptions writeConnectionOptions = new CosmosClientOptions();
writeConnectionOptions.ConnectionMode = ConnectionMode.Direct;
writeConnectionOptions.ApplicationRegion = "West US";
CosmosClientOptions readConnectionOptions = new CosmosClientOptions();
readConnectionOptions.ConnectionMode = ConnectionMode.Direct;
readConnectionOptions.ApplicationRegion = "East US";
writeClient = new CosmosClient(accountEndpoint, key, writeConnectionOptions);
readClient = new CosmosClient(accountEndpoint, key, readConnectionOptions);
}
}
After we’ve set up our client, we can now set up custom synchronization like so:
class MyDataAccessLayer
{
public async Task CreateItem(string databaseId, string containerId, dynamic item)
{
ItemResponse<dynamic> response = await writeClient.GetContainer("containerId", "databaseId")
.CreateItemAsync<dynamic>(
item,
new PartitionKey("test"));
await readClient.GetContainer("containerId", "databaseId").ReadItemAsync<dynamic>(
response.Resource.id,
new PartitionKey("test"),
new ItemRequestOptions { SessionToken = response.Headers.Session, ConsistencyLevel = ConsistencyLevel.Session });
}
}
Hopefully this short article has given you a bit of an introduction into consistency levels in Azure Cosmos DB. Cosmos DB has the advantage over other distributed databases by providing us with 5 defined levels of consistency rather than just 2 extremes. This can provide us with some flexibility depending on the durability and availability needs for our application.
If you have any questions or comments, feel free to comment below!
Top comments (0)