Did you hear about eBay using MongoDB as their primary database? Now, why would a multinational e-commerce firm like eBay use MongoDB and not a traditional RDBMS? It’s because MongoDB has been a hot topic among the developers for its distributed key-value store and document-oriented NoSQL features. And, if eBay is using it then I’m sure that your e-commerce application uses MongoDB as well.
Forget eBay. Let’s take your e-commerce application and dissect its basic data and performance needs. Now in your .NET/.NET Core app, have you ever felt like the performance is compromised because you have limited requests per second? Have you noticed the time delay in read/write calls to your disk-based database? Have you had a feeling that even with all its wonderful features, MongoDB still lacks a certain link that could bring your application glory?
This, my friend, is where somebody (me) pokes you (only virtually) and introduces NCache in your life. NCache is an in-memory, distributed, and highly scalable cache that stays right next to your application at all times; improving transaction rate and hence making it the perfect solution for all your caching needs. Let’s take a little tour of how you can get the best out of your application using NCache.
NCache Details Sync Cache with Database NCache NoSql Datastore
Using NCache as a Distributed Cache with MongoDB
With a high transactional e-commerce application like yours that runs in a multi-server environment, you can’t afford to have a single server cache entertaining all your data requests. The greater the load on your application gets, the more are the chances of your cache choking on the requests.
There may come a time during the execution of your application where the transaction load on your application increases and the number of cache servers initially set up is not quite enough to entertain the incoming requests. This is where NCache seamlessly scales your application by allowing you to add additional cache servers at runtime so the cache never becomes a bottleneck for your application. Hence, ensuring optimum performance in your .NET/.NET Core application.
To get a proper image of where exactly NCache sits within your application stack, let’s take a look at the basic architecture.
MongoDB is considered more scalable compared to relational databases but the fact that it is a disk-based data store remains a drawback. So, using NCache provides you with memory-based data caching while staying either inside or outside your app’s VNet (totally your call). This makes your application processes way faster than wanted, hence reducing latency.
Doesn’t this give you more of the reason to use NCache for caching your database’s data? Let’s not stop here and dive a little deeper into what NCache brings to the table.
NCache Details Sync Cache with Database NCache NoSql Datastore
How to Cache with MongoDB
Caching with MongoDB is extremely easy. Whether you want to search for a specific data in the cache, or query the database itself to fetch the required data, or just simply add new data to the database, it can all be done with utmost ease using NCache.
The following snippet explains how to perform all these aforementioned operations in your e-commerce application. Here we search for a very loyal and intelligent customer of yours, Einstein, in the cache to perform CRUD operations on it. And in case the cache doesn’t have the requested customer, we search the database for it. Once retrieved, we add that customer to the cache with an expiration of 5 minutes. This is done so that the cache never has stale data to offer you. Hence, ensuring data consistency.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var customer = cache.Get("Customer:CustomerID:EINSTEIN"); if (customer == null) { MongoClient mongoClient = new MongoClient("mongodb://20.200.20.10:27017"); IMongoDatabase mongoDatabase = mongoClient.GetDatabase("DemoDatabase"); IMongoCollection <Customer> mongoCollection = mongoDatabase.GetCollection<Customer>("Customers"); response = mongoCollection.FindAsync<Customer>(x => x.Id == "EINSTEIN").GetAwaiter().GetResult().ToList<Customer>(); customer = (Customer)response.FirstOrDefault(); var expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)); var cacheItem = new CacheItem(customer) { Expiration = expiration }; cache.Insert($"Customer:CustomerID:{customer.Id}", cacheItem); } |
NCache Details Sync Cache with Database NCache NoSql Datastore
Caching Collection of Database Items
The biggest perk of introducing NCache to your application and the database is that the trips to the database especially for read operations reduce considerably, reducing unnecessary network calls and improving performance. The sole reason for this logical placement is that every time you want to retrieve items from the database and perform operations on it, you can do it all in the caching tier.
To accomplish this, NCache allows you to cache a MongoDB collection as a cache item or an individual item as a one cache item. Let us look at how to cache items as key-value pairs in NCache from MongoDB.
Cache Collection as Single Item
Caching a collection of items as a single CacheItem comes in handy when the items are similar or fall under the same category. For example, let’s assume that your application’s database has a list of worldwide spread customers but you want to query the ones that live in Germany (because your ever-favorite Einstein is from Germany). You want this query to return all these customers in the form of a single list so that this list can be added to the cache. Here’s how you do that:
1 2 3 4 5 6 7 |
var customersInGermany = mongoCollection.FindAsync(x => x.Country == 'Germany').GetAwaiter().GetResult().ToList(); if(customersInGermany > 0) { var expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)); var cacheItem = new CacheItem(customersInGermany) { Expiration = expiration }; cache.Insert("CustomersInGernamy", cacheItem); } |
Cache Collection Items Separately
In case you want to associate additional information with each item like tags, name tags, and groups to make data retrieval easier, then you should cache each item separately using unique identifiers. This way, you can retrieve multiple items based on a logical tag, for example, all customers living in Germany.
To cache all customers that live in Germany, you can add the tag Customer:Country:Germany
with the dataset of the query. Here’s an example of how to cache all German customers with the “Germany” tag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var customersInGermany = mongoCollection.FindAsync(x => x.Country == 'Germany').GetAwaiter().GetResult().ToList(); if(customersInGermany > 0) { var expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)); foreach (var customer in customersInGermany) { cacheItem = new CacheItem(customer) { Tags = new[] { new Tag("Customer:Country:Germany") }, Expiration = expiration }; cache.Add($"Customer:CustomerID:{customer.Id}", cacheItem); } } |
To this point, we have discussed in detail how to juggle data between your application and MongoDB using NCache. You can tell how easy it is to access and manipulate data by performing CRUD operations on it all because of NCache. Let me now take you on a brief tour of how NCache brings efficiency to the dish; the cherry on top if you may.
Here are some of the features that NCache provides to enhance your e-commerce application performance that uses MongoDB.
NCache Details Sync Cache with Database NCache NoSql Datastore
Eradicate Serialization Cost with JSON Serialized Cache
MongoDB stores data in the form of Binary JSON (BSON), which is the binary-encoded serialization of JSON-like documents. This works perfectly well with NCache as it supports the JSON serialization of objects. This MongoDB-NCache collaboration not only improves your application’s performance time by preventing the need to serialize/deserialize data but also sustains the accuracy of your data.
1 2 3 4 5 |
var response = mongoCollection.FindAsync<Customer>(x => x.Id == "EINSTEIN").GetAwaiter().GetResult().ToList<Customer>(); Customer customer = (Customer)response.FirstOrDefault(); JObject customerJson = JObject.Parse(JsonSerializer.Serialize(customer)); cache.Insert($"Customer:CustomerID:{customer.Id}", customerJson); customer = cache.Get<Customer>($"Customer:CustomerID:EINSTEIN "); |
Data Source Providers for Resource Optimization
NCache provides Data Source Providers to ensure single point entry into the data access layer of your application; the entry point being your cache. In case the data isn’t available in the cache, a Read-Through provider is responsible for accessing the database, searching and retrieving the required data, caching it for future use, and presenting it to the application.
1 |
var customer = cache.Get<Customer>( "EINSTEIN", new ReadThruOptions(ReadMode.ReadThru, "mongoDBReadThroughProvider")); |
Similarly, you have a Write-Through provider for when you want to execute a write operation on the database. You simply have to perform the required operation on the cache and the cache will automatically write the data in the database for you. Let’s add “Einstein 2” in the cache so that it adds the 2.0 version of your favorite customer in the database using WriteThru
.
1 2 3 4 |
Customer customer = new Customer(); customer.Id = "EINSTEIN2"; ... cache.Insert(customer.Id,new CacheItem(customer),new WriteThruOptions(WriteMode.WriteThru,"mongoDBWriteThroughProvider"); |
NCache Details Sync Cache with Database NCache NoSql Datastore
Query Cache Data
When using NCache as the intermediary caching layer between your .NET application and MongoDB, NCache offers you the ability to search indexed cached data through querying. Querying in-memory cache data directly reduces the trip cost that a query should normally take over a network.
An example code snippet depicting the use of querying indexed data in NCache is shown here:
1 2 3 4 5 6 7 8 9 10 11 12 |
string query = "SELECT * FROM Models.Customer WHERE Country == ?"; var queryCommand = new QueryCommand (query); queryCommand.Parameters.Add("Country", "Germany"); ICacheReader reader = cache.SearchService.ExecuteReader(queryCommand); if (reader.FieldCount > 0) { while (reader.Read()) { string result = reader.GetValue("ContactName"); // Perform operations } } |
Concluding it All
Considering all of the functionalities and features that NCache offers you, it is safe to conclude that no better match can be made than NCache caching MongoDB. Here’s why. MongoDB lies away from your application; you need a solution that stays close for increased performance: NCache provides that by being in-memory. You need a solution that lets you add any number of servers at runtime: linearly scalable NCache brings that to you. You are looking for a flexible solution that dynamically auto-rebalances your data: NCache does exactly that plus without any client interference.
NCache offers way too much in the form of performance, cost reduction, flexibility, scalability, so what else are you looking for then? Go get NCache and enjoy caching!