CRUD Operations: An Overview
NCache stores data as key-value pairs, i.e., unique identifiers (key) are stored against a data (value). Similar to a key-value database, NCache also stores, retrieves and manages data through CRUD operations. In this regard, NCache provides a diverse set of CRUD APIs for caching atomic or bulk data, both synchronously or asynchronously. Here, we provide an overview of NCache-supported basic CRUD operations: Add, Insert, Get, and Remove.
Before moving forward, you must know what to store in the cache. Besides the conventional string-based values, NCache allows adding primitive data types, custom objects, data with metadata (CacheItem), data structures, and JSON data.
Any object added to the cache must be serializable. NCache handles binary and JSON serialization based on your store format. If you cannot perform native binary serialization, NCache also provides its own Compact Serialization Framework. For the JSON store, NCache handles the serialization for the provided objects. Alternatively, you can add NCache provided JSON serialized objects, which enables support for cross-platform and multi-language applications.
NCache allows CRUD operations on single or bulk items. Meanwhile, supported operation modes are synchronous and asynchronous. Here we briefly explain operation types and modes in NCache.
We categorize all the operations performed on single key-value pair as atomic operations. Hence, such operations require a single cache call. The behavior of atomic add, insert, remove, and get operations will be discussed in later sections.
Bulk operations allow you to perform any CRUD operation on multiple items through a single cache call. Although a bulk operation executes as a single operation, the failure of operations is treated individually. They are specifically designed to enhance performance. For instance, retrieving 100 cache items in a single bulk operation performs much faster than retrieving them through 100 atomic calls. In this way, performance improves due to reduced network trips to the remote server.
Bulk operations are particularly useful to fetch cached data in bulk at the start of an application or insert a query result as bulk into the cache.
NCache allows adding either an atomic item or a bulk of items synchronously. Since synchronous operations occur as a blocking call, the client has to wait for the response from the server to execute further operations. The control returns to the application once the operation takes place.
Although the client has to wait for operation completion, sync operations allow returning the success/failure status of the operation as the control returns to the user. Such an operation may fail due to connection failure with the cache or internal system errors. This process provides applications with the control to handle any failure scenarios as soon as they are encountered. Hence, these operations are essential when you are processing critical data.
Furthermore, synchronous operations are sequential. This is useful if your operations are dependent on each other. For example, an e-commerce site synchronously adds items that are on flash sale for 2 hours only and later on retrieves those items which have a flash sale. While fetching the cached items on sale, failure can be avoided if it ensures that these items were successfully added to the cache first. The basic CRUD operations are synchronous by default if not stated otherwise.
This feature is only available in NCache Enterprise Edition.
Asynchronous operations occur in the background, so the client does not have to wait for the response from the server to execute further operations. The list of actions to be performed on the cache is maintained in a queue on the client side, and a dedicated background thread keeps on sending them to the server side. The control returns to the application immediately after an operation is queued. This increases the overall responsiveness of the application.
Asynchronous operations can be useful when response time is critical for your application and failure of operations doesn't hinder the working of your application.
Since asynchronous operations do not notify upon the failure or success of the operations themselves, the asynchronous calls in NCache return an object of the Task class which can be further used to get the status of the operation. In this regard, the following status flags are provided by the Task class to indicate the success or failure of the operation performed.
- IsCompleted: Notifies if the specified operation occurs successfully in the cache.
- IsFaulted: Notifies if the specified operation occurs but fails.
- IsCanceled: Notifies if the specified operation is canceled due to any internal reason.
Basic CRUD in Distributed Cache
You can interact with the cache once you get an instance of a cache. Let's see the working and behavior of basic CRUD operations supported by NCache.
Items can be added to the cache using Add or Insert method. However, both operations differ in behavior.
Add successfully adds an item to the cache with a specific key only when the provided key doesn't exist in the cache and throws an exception otherwise. Let's say you want to prohibit adding an item to the cache by multiple clients at a time. Then you can use the
Add method to notify operation failure if a client tries to add an item already existing in the cache.
On the other hand,
Insert also works as an update operation. If you add an item using the
Insert method, and the specified key already exists in the cache, the existing item in the cache is replaced. Besides adding items, it safely updates items in the cache.
The simplest case is to directly add or insert an item to the cache by specifying a key and value. However, these methods have several overloads that allow you to add/insert items into the cache with advanced options. The relevant use cases and behaviors of Add/Insert are discussed below.
Add bulk of data: A collection of data can be added to the cache simultaneously using the
AddBulkcan be used if you specifically request notifications of failure to add items with existing keys. In this regard, the failed operations are highlighted individually by returning a dictionary specifying the corresponding keys with the exception to the application. For instance, if a bulk of 100 items are added to the cache and 20 of those items already exist in the cache, the remaining 80 items will be added to the cache. The existing 20 items will be returned to the application as a dictionary of failed operations.
In case you want to avoid failure while adding multiple items to update the existing items, you can use the
InsertBulkmethod. It overwrites the existing items in the cache and returns a dictionary of keys that failed to add/update for any reason.
Add data asynchronously: Items can be added/inserted to the cache asynchronously when you want to improve the efficiency of the client application.
InsertAsyncmethods add the items in the background and return the Task object once the operation is completed. The client can check the status flags mentioned in Asynchronous Operations to verify the success or failure of add/insert operation without any extra code.
Add data with dependencies: You can add/insert items to the cache with dependencies. Since cache data is temporary, certain data may need to be removed from the cache based on user-specific criteria. In that case, NCache provides various ways to invalidate cached data by allowing you to set dependencies while adding/inserting items. Specifically, you can set dependencies based on time, cache data, database, and external source to invalidate and eventually remove certain items as per your application requirement.
Concurrent write: You can insert items to the cache with locking to control simultaneous access in case of multithreaded or multi-client applications. It helps to maintain data integrity when concurrent update operations are performed in the cache. You can either lock an item exclusively or work on a version of the item added to the cache. The item version is maintained by the cache for every item in the cache, and it is auto-incremented every time the update operation is performed.
Write to the data source: In advanced cases if the data source is configured, data will be added/updated in the cache as well as in the data source during the add/insert operation. For more details, refer to the chapter Data Source Providers.
Request execution flow: When add/insert operation occurs, the underlying request execution process follows these steps: serialization, encryption, and compression. First, the provided data is serialized. Then it is encrypted at the client end if encryption is configured. Since data traveling through the network can be easily intercepted, you can encrypt your sensitive data using NCache Data Encryption feature to protect it from security risks. Finally, the encrypted data is compressed if compression is enabled. Since the available bandwidth and memory are scarce, NCache Data Compression feature allows you to significantly reduce the network traffic and memory consumption. Eventually, your write operations are performed faster.
Primarily, a cache is considered effective based on its ability to retrieve data. An item can be retrieved from the cache using the
Get operation by specifying the key against which the item was stored. In case the specified item doesn't exist in the cache, a null value returns without an exception.
Get bulk of items: Multiple items can be retrieved from the cache simultaneously using the
GetBulkmethod. It retrieves the items found in the cache in the form of a key-value dictionary. No exception is thrown if any of the specified keys don't exist in the cache.
Verify the existence of items: Since the cache is volatile, you may need to know if an item exists in the cache or not. The existence of an item can be determined using NCache provided
Containsmethod. Moreover, the existence of multiple items can be verified through the
Get from data source: In advanced cases if the data source is configured, data will be fetched from the data source if it does not exist in the cache. For more details, you can refer to the chapter Data Source Providers.
To manage stale data and cache storage efficiently, you may need to remove data explicitly. You can easily remove items from the cache using the
Remove method. If the specified key doesn't exist in the cache, a null value is returned. You can also obtain the removed item for further processing based on your application need. However, the cost of fetching objects on removal is inevitable. Therefore, the prior approach is recommended when you don't need the items on removal.
Remove bulk items: A collection of items can be removed from the cache simultaneously using the
RemoveBulkmethod. You can also retrieve the successfully removed items in a dictionary. However, it can be slow depending on the size of the objects retrieved on removal. Hence, it is recommended to simply remove the items since it is more efficient when you don't need to process the removed items.
Remove items asynchronously: You can remove atomic data from the cache asynchronously using the
RemoveAsyncmethod. The item will be removed in the background, and upon operation completion, you will receive the status. In case you want to verify whether that item is successfully removed or not, you can use the provided status flags for async operations.
Remove from data source: In advanced cases, if the data source is configured, data removal will occur in the cache as well as in the data source. For more details, you can refer to the chapter Data Source Providers.
RemoveAsync does not return the removed objects to the application.
In this Section
Add Data to Cache
Explains how to add data into cache.
Update Existing Data in Cache
Explains how to update data existing in cache.
Remove Data from Cache
Explains how to remove data from cache.
Retrieve Existing Cache Data
Explains how to retrieve data from cache.