Sync Cached Data With Cosmos DB Using NCache

Introduction
 

What is CosmosDB?

Azure Cosmos DB is a fully managed and globally distributed multi-model cloud-based NoSQL database service. It is fully managed because of its simplicity of deployment and comprehensive service level agreements (SLAs) from Microsoft. It supports flexible JSON format which means it supports unstructured and JSON data and easy to store data with very less code.

Common use cases of CosmosDB 

  1. IoT – To ingest, process and store data 
  2. Gaming – used in social media integration, high-score leaderboards and many other
  3. Retail and marketing – For storing lookup data, event sourcing in order processing pipelines 
  4. Web and Mobile Application – Integrating with third-party services, storing data and personalization 

NCache with CosmosDB

We can further enhance or scale up the performance of CosmosDB with NCache. NCache is an Open Source in-memory distributed cache for .NET, Java, and Node.js. NCache is extremely fast and linearly scalable and caches application data to reduce expensive database trips. 

NCache sits much closer to your application and hence is much faster to access. 

From this article, you will learn how to integrate distributed caching into your Azure Cosmos DB application by using NCache and data sync between Azure Cosmos DB and NCache using Azure functions.

Primary Problems in CosomsDB
 

1. Performance Bottleneck 

Microsoft Azure claims that Cosmos DB is going to give you a millisecond response time, alright, what if your solution will cut down a second to millisecond and millisecond to sub millisecond response time? It is possible by Incorporating the NCache with CosmosDB. 

ComosDB is a hosted service so it will be across VNET in its own subscription, which increases the latency part, the performance of your cosmos DB is going to be degraded specifically under high transaction/loads. When you have a lot of requests coming in and you need to deal with that data in a fast timely manner. Accessing it across your VNET is very slow and think about accessing it from On-premise App when there is high traffic. This is where a distributed cache such as NCache comes into picture. You can cache the frequently accessed data to improve response times. The distributed nature of caching in NCache for Azure CosmosDB ensures optimal performance under extreme transaction loads by making the cache linearly scalable too.

2. High Cost 

Cost is one of the major factors when it comes to Azure Cosmos DB. Each time when you try to access Microsoft Azure Cosmos DB, even for the read-only data it costs because the cost plan is something based on the request unit. If that data is not being changed that frequently, it's the same content but you still have the master source coming from the Cosmos DB that's the data that you're looking in. For that data, you have to keep going back and forth to Microsoft Azure Cosmos DB and that's where you pay in terms of request unit and that increases your cost. So, costs would go up if your request load increases. The usage cost goes up and it is an issue specifically for Read-only data.

So, it's very scalable, as far as requests load that it can handle but it's not going to be very cost friendly in that scenario. So, it's going to impact the cost factor as well. So, it could be a potential hurdle for scaling out. When you're planning to scale out. You have multiple partitions; you have your data load increasing but the cost factor goes up alongside that. Ncache integration with ComosDB will be very handy when it comes to cost factor because you can reduce number of request unit by caching the frequently requested data in Ncache distributed caching service 

Let’s go through following topics with demo 

  1. App data caching with Cosmos DB
  2. Sync NCache with Azure CosmosDB

App data with CosmosDB

Before starting, we should have Azure CosmosDB to integrate it with NCache. I have created an Azure CosmosDB using Azure portal and downloaded the sample code for .NET from the quick start section.

Install NCache Manager 

Download NCache from NCache Download Center (alachisoft.com). I highly recommend you to install the Enterprises edition so that you can explore all the features. Before the installation make sure .NET 6 has been installed on your machine. 

After completing the Download and installation process, you can run the NChace Web Manger in the browser from localhost 8251 port, as shown in the below figure.

We can create a clustered and Local Caches from the NCache Manager application.

For this demo, I have created a local cache and named it as “myLocalCache” using Ncache Manager as shown in the below figure.

Click here to check how to create a local Cache using NCahce Web Manager.

Open the Sample cosmosDB quick start source code in visual studio and run it. It will add a new item to the database as shown in below figure. 

Install Alachisoft.NCache.SDK package from NuGet package manager 

Before running the application, check the statistics of your local cache using NCache web Manager.  The count will be zero as shown in the below figure,

Add a below function, in the application. 

private async Task GetFamily(Family family) {
    try {
        string key = $ "Family:FamilyID:{family.Id}";
        Family familyResult = _NCacheClient.Get < Family > (key);
        if (familyResult != null) {
            Console.WriteLine(familyResult.PartitionKey);
        } else {
            var sqlQueryText = "SELECT * FROM c";
            QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText);
            FeedIterator < Family > queryResultSetIterator = this.container.GetItemQueryIterator < Family > (queryDefinition);
            while (queryResultSetIterator.HasMoreResults) {
                FeedResponse < Family > currentResultSet = await queryResultSetIterator.ReadNextAsync();
                foreach(Family familyTemp in currentResultSet) {
                    if (familyTemp.Id == family.Id) {
                        _NCacheClient.Insert(key, familyTemp.ToString());
                        Console.WriteLine("\tRead {0}\n", familyTemp.LastName);
                    }
                }
            }
            Console.WriteLine(familyResult.LastName);
        }
    } catch (Exception ex) {
        //TODO
    }
}

This function will check if the the key is present in the cache or not. If the key is available in cache it will fetch data from the cache using the cache or else it will fetch the data from cosmosDB and insert it into Cache using the Insert function. 

Now check the NCahce statistics, the count will be increased to 1 as shown in below figure, which means the record has been inserted into the local cache server.

When you run the program next time, it will fetch the record from Local cache server based on key.

Syncing NCache with Azure CosmosDB

Synchronization is a big aspect when your data exist in two different places. Each time when there is a change in the cache you also apply those changes in the database as well. But what happens if data changes directly in CosmosDB and that’s going to most natural scenario where CosmosDB getting updated by another service. 

Whatever the changes are done in CosmosDB will not reflect in the cache, right now these two sources are out of sync. We need to have some kind of synchronization mechanism between Azure CosmosDB and NCache.

There are two ways you can sync NCache with Azure CosmosDB 

  1. Azure function with CosmosDB Trigger
    • Implicit change feed processing
    • Sync Insert & update and Delete operation
  2. Custom change Feed processor
    • Implement IChangeFeedObserver interface explicitly
    • Sync Insert, update and delete operations

Azure Function with CosmosDB Trigger

Using Azure function, it is very easy to sync the changes in ComosDB to cache.

Create an Azure function using Visual Studio with the CosmosDB Trigger

Copy your CosmosDB Connection string from azure portal to Connection string setting name.

Replace the code in Function1.cs file with below code.

[FunctionName("Function1")]
public static void Run([CosmosDBTrigger(databaseName: "ToDoList", collectionName: "Items", ConnectionStringSetting = "<Your CosmosDB Connection string>", LeaseCollectionName = "leases")] IReadOnlyList < Document > input, ILogger log) {
    try {
        if (input != null && input.Count > 0) {
            Family family = null;
            using(var cache = CacheManager.GetCache("myLocalCache")) {
                foreach(var document in input) {
                    family = new Family {
                        LastName = document.GetPropertyValue < string > ("LastName"),
                            Id = document.GetPropertyValue < string > ("Id")
                    };
                    cache.InsertAsync(family.Id, family);
                }
            }
        }
    } catch (Exception ex) {
        //ToDo
    }
}

Run the azure function, go to your cosmosDB in Azure portal and modify the collection, in my case I have updated the LastName from the family collection, the moment when you update the collection the CosmosDB trigger the azure function which will Insert the updated collection in the cache using InsertAsync function.

Go to cache statistic and check the count. 

It’s just a sample to show you how to sync the CosmosDB with Ncache with the help of Azure function. Not only update you can capture any collection add or delete in CosmosDB and sync with your cache server. Hard delete is not supported in ComosDB but there is workaround to do a soft delete. Will see more about syncing delete and add collection with cache in my next article. 

Summary

We saw what is NCache and how to integrate it with CosmosDB to cache the data. Later we went through the demo of CosmosDB sync with NCache server with the help of Azure functions with CosmosDB trigger. We will see more about Syncing cached data with Cosmos DB using NCache with Custom change Feed processor in my next article.

Get complete source code on GitHub