NCache as HybridCache Provider
The NCache HybridCache integration provides a high-performance, two-tier caching strategy that combines the speed of local memory with the scale of a distributed cluster:
- L1 Cache (In-Proc): An In-Proc local cache. This resides within your application's memory space for microsecond access. Each application instance has its own L1.
- L2 Cache (Distributed): A Replicated cache. This acts as the shared source of truth for all application nodes in the cluster.
Note
This feature is currently supported in the NCache OpenSource edition.
Important
HybridCache is supported in NCache 5.3.6.2 and onwards.
NCache orchestrates these tiers through the Pub/Sub Backplane. When one server updates or removes a value, NCache automatically broadcasts a message to all other servers to update their local L1 memory from L2 distributed cache, ensuring your cluster stays in sync.
There are two ways to configure NCache as a HybridCache provider in ASP.NET Core depending on your environment and deployment needs:
- Using appsettings.json (Recommended for Production)
- Using an Action Delegate in Program.cs
How the Pub/Sub Backplane Works
The Pub/Sub backplane operates completely transparently. It requires no manual configuration, subscription management, or maintenance, running automatically in the background from the moment your application starts. On startup: During Dependency Injection (DI) initialization, the NCache HybridCache provider establishes a connection to the remote NCache cluster and subscribes to a dedicated, internal Pub/Sub topic. Every application instance (node) maintains its own subscription to this topic to ensure cluster-wide cache synchronization.
When any node calls SetAsync or RemoveAsync:
- The value is written to (or removed from) the L2 NCache cluster.
- The provider publishes a message on the internal Pub/Sub topic containing the affected key.
- Every other subscribed node receives the message and immediately evicts or refreshes that key in its own L1 cache.
When any node calls RemoveByTagAsync:
Tag invalidation uses a lightweight logical approach rather than a bulk delete which is important for performance at cluster scale:
- Instead of deleting every item that carries the tag, NCache writes a single sentinel timestamp for the tag into the L2 cluster. This is always one write, regardless of how many cached items carry that tag.
- The provider publishes a Pub/Sub message broadcasting the tag invalidation.
- Every node receives the message and records the sentinel locally.
- From this point forward, on any node, when
GetOrCreateAsyncretrieves an item, NCache compares the item's creation time against the tag's sentinel timestamp. If the tag was invalidated after the item was created, the item is treated as stale and the factory is called to produce a fresh value.
Prerequisites
Before using the HybridCache with NCache, ensure that the following prerequisites are fulfilled:
- Install the following NuGet package in your application:
- OpenSource: NCache.OSS.Microsoft.Extensions.Caching.Hybrid
- To utilize the HybridCache provider, include the following namespace in Program.cs:
NCache.OSS.Microsoft.Extensions.Caching.Hybrid
- You must have two caches running, i.e., L1 and L2 cache.
- Make sure that the data being added is serializable.
Method 1: Using appsettings.json
This is the recommended approach to manage your cache settings as it allows configuration changes without needing to recompile the application. First, define the configuration section in appsettings.json of your project.
{
"NCacheHybridCache": {
"LocalCacheName": "myLocalCache",
"LocalCacheExpiration": "00:05:00",
"DistributedCacheName": "myDistributedCache",
"DistributedCacheExpiration": "00:30:00",
"ServerList": [
{
"Ip": "20.200.20.39",
"Port": 9800
},
{
"Ip": "20.200.20.40",
"Port": 9800
}
]
}
}
Then, in your Program.cs, register the service:
var builder = WebApplication.CreateBuilder(args);
// Method 1: Using specific configuration section
var config = builder.Configuration.GetSection("NCacheHybridCache");
builder.Services.AddNCacheHybridCache(config);
// OR Method 2: Auto-detect configuration section
builder.Services.AddNCacheHybridCache(builder.Configuration);
// Build the application
var app = builder.Build();
app.Run();
Note
To ensure the operation is fail-safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
The parameter breakdown for appsettings.json is as follows:
Note
The parameters with asterisk (*) on their names are the required parameters and the rest are optional.
| Parameters | Description |
|---|---|
| LocalCacheName* | Specifies the name of the NCache In-Proc cache used as local cache (L1). It must be created in NCache before application startup and runs in application process memory for fast access (microseconds). |
| DistributedCacheName* | Specifies the name of the NCache distributed cache used as distributed cache (L2). It must be created in NCache before application startup. Shared across all application instances for data consistency. |
| LocalCacheExpiration | Indicates how long items are retained in the local cache before expiration. If null, local caching is disabled. Should typically be shorter than DistributedCacheExpiration to balance performance and data freshness. |
| DistributedCacheExpiration | Indicates the expiration time for items stored in the distributed cache. If null, uses distributed cache provider's default expiration. It should typically be longer than LocalCacheExpiration. |
| ServerList | Consists of your cluster nodes. You should list at least one server. Each entry specifies IP address and port (default value 9800). |
Method 2: Using an Action Delegate in Program.cs
This method involves setting the configuration properties directly within your code during the service registration.
var builder = WebApplication.CreateBuilder(args);
// Register NCache Hybrid Cache service with custom configuration
builder.Services.AddNCacheHybridCache(options =>
{
// Name of the in-memory (local) cache
options.LocalCacheName = "myLocalCache";
// Expiration time for items stored in local cache
options.LocalCacheExpiration = TimeSpan.FromMinutes(5);
// Name of the distributed cache (shared across multiple instances)
options.DistributedCacheName = "myDistributedCache";
// Expiration time for items stored in distributed cache
options.DistributedCacheExpiration = TimeSpan.FromMinutes(30);
// List of cache server nodes for distributed cache
options.ServerList = new List<ServerConfig>
{
// First cache server configuration, default port 9800 if not specified
new ServerConfig { Ip = "20.200.20.39", Port = 9800 },
// Second cache server configuration, default port 9800 if not specified
new ServerConfig { Ip = "20.200.20.40", Port = 9800 }
};
});
// Build the application
var app = builder.Build();
Logging in HybridCache
NCache HybridCache employs the standard ASP.NET Core logging infrastructure via the Logger interface. Configuration is managed through the standard Logging section in your appsettings.json. The cache automatically utilizes the logger instance injected by the Dependency Injection (DI) container.
- Use
DebugorInformationlogging level for detailed insights into cache operations (e.g., L1/L2 hits and misses). - Use
WarningorErrorto minimize log overhead in case of critical issues.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"NCache.Microsoft.Extensions.Caching.Hybrid": "Debug"
}
}
}
All logs are tagged with the category NCache.Microsoft.Extensions.Caching.Hybrid. You can target this specific namespace in your configuration to filter NCache logs independently from the rest of your application.
Important
Logging is managed entirely through ASP.NET Core via standard providers.