FusionCache is an easy to use, fast and robust hybrid cache with advanced resiliency features.
$ dotnet add package ZiggyCreatures.FusionCacheIt was born after years of dealing with all sorts of different types of caches: memory caching, distributed caching, http caching, CDNs, browser cache, offline cache, you name it. So I've tried to put togheter these experiences and came up with FusionCache.
It uses a memory cache (any impl of the standard IMemoryCache interface) as the primary backing store and optionally a distributed, 2nd level cache (any impl of the standard IDistributedCache interface) as a secondary backing store for better resilience and higher performance, for example in a multi-node scenario or to avoid the typical effects of a cold start (initial empty cache, maybe after a restart).
FusionCache also includes some advanced features like a fail-safe mechanism, concurrent factory calls optimization for the same cache key, fine grained soft/hard timeouts with background factory completion, customizable extensive logging and more (see below).
These are the key features of FusionCache:
GetOrSet[Async] method prevents multiple concurrent factory calls per key, with a guarantee that only 1 factory will be called at the same time for the same key (this avoids overloading the data source when no data is in the cache or when a cache entry expires)IDistributedCache interface is supported (eg: Redis, MongoDB, SqlServer, etc)ILogger interface (you can use Serilog, NLog, etc)Also, FusionCache has some other nice additional features:
null"JitterMaxDuration will add a small randomized extra duration to a cache entry's normal duration. This is useful to prevent variations of the Thundering Herd problem in a multi-node scenarioFusionCache can be installed via the nuget UI (search for the ZiggyCreatures.FusionCache package) or via the nuget package manager console:
PM> Install-Package ZiggyCreatures.FusionCache
As an example, imagine having a method that retrieves a product from your database:
Product GetProductFromDb(int id) {
// YOUR DATABASE CALL HERE
}
💡 This is using the sync programming model, but it would be equally valid with the newer async one for even better performance.
To start using FusionCache the first thing is create a cache instance:
var cache = new FusionCache(new FusionCacheOptions());
If instead you are using DI (Dependency Injection) use this:
services.AddFusionCache();
We can also specify some global options, like a default FusionCacheEntryOptions object to serve as a default for each call we'll make, with a duration of 2 minutes and a Low priority:
var cache = new FusionCache(new FusionCacheOptions() {
DefaultEntryOptions = new FusionCacheEntryOptions {
Duration = TimeSpan.FromMinutes(2),
Priority = CacheItemPriority.Low
}
});
Or, using DI, like this:
services.AddFusionCache(options => {
options.DefaultEntryOptions = new FusionCacheEntryOptions {
Duration = TimeSpan.FromMinutes(2),
Priority = CacheItemPriority.Low
}
});
Now, to get the product from the cache and, if not there, get it from the database in an optimized way and cache it for 30 sec simply do this:
var id = 42;
cache.GetOrSet<Product>(
$"product:{id}",
_ => GetProductFromDb(id),
TimeSpan.FromSeconds(30)
);
That's it 🎉
FusionCache targets .NET Standard 2.0, so any compatible .NET implementation is fine.
NOTE: if you are running on .NET Framework 4.6.1 and want to use .NET Standard packages Microsoft suggests to upgrade to .NET Framework 4.7.2 or higher (see the .NET Standard Documentation) to avoid some known dependency issues.