Reference:
https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-9.0
https://learn.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-9.0#distributed-memory-cache
Thanks for learning code from Zack.Yang
Caching can significantly improve the performance and scalability of an app by reducing the work required to generate content. Caching works best with data that changes infrequently and is expensive to generate. Caching makes a copy of data that can be returned much faster than from the source. Apps should be written and tested to never depend on cached data.
Simple example for In-Memory Cache
1.Add Memory Cache services
builder.Services.AddMemoryCache();
2.Dependency injection through constructor
private readonly IMemoryCache memoryCache;
public MemoryCacheHelper(IMemoryCache memoryCache)
{
this.memoryCache = memoryCache;
}
3.Invoke related functions
private static void InitCacheEntry(ICacheEntry entry, int baseExpireSeconds)
{
//过期时间.Random.Shared 是.NET6新增的
double sec = Random.Shared.NextDouble(baseExpireSeconds, baseExpireSeconds * 2);
TimeSpan expiration = TimeSpan.FromSeconds(sec);
entry.AbsoluteExpirationRelativeToNow = expiration;
}
public async Task<TResult?> GetOrCreateAsync<TResult>(string cacheKey, Func<ICacheEntry, Task<TResult?>> valueFactory, int baseExpireSeconds = 60)
{
ValidateValueType<TResult>();
// get from memory cache
if (!memoryCache.TryGetValue(cacheKey, out TResult result))
{
using ICacheEntry entry = memoryCache.CreateEntry(cacheKey);
// build a CacheEntry, this is the data cached in memory
InitCacheEntry(entry, baseExpireSeconds);
// get the data and store it in the memory
result = (await valueFactory(entry))!;
entry.Value = result;
}
return result;
}
A distributed cache is a cache shared by multiple app servers, typically maintained as an external service to the app servers that access it. A distributed cache can improve the performance and scalability of an ASP.NET Core app, especially when the app is hosted by a cloud service or a server farm.
A distributed cache has several advantages over other caching scenarios where cached data is stored on individual app servers.
Simple example for distributed cache (Redis)
1.Install Nuget:
Microsoft.Extensions.Caching.StackExchangeRedis
2.Add distributed cache services
builder.Services.AddStackExchangeRedisCache(options =>
{
// redis connect string
options.Configuration = "localhost:6379";
options.InstanceName = "SelfLearnProject_";
});
3.Dependency Inject from constructor
private readonly IDistributedCache distCache;
public DistributedCacheHelper(IDistributedCache distCache)
{
this.distCache = distCache;
}
4.Invoke related functions
private static DistributedCacheEntryOptions CreateOptions(int baseExpireSeconds)
{
//过期时间.Random.Shared 是.NET6新增的
double sec = Random.Shared.NextDouble(baseExpireSeconds, baseExpireSeconds * 2);
TimeSpan expiration = TimeSpan.FromSeconds(sec);
DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
options.AbsoluteExpirationRelativeToNow = expiration;
return options;
}
public async Task<TResult?> GetOrCreateAsync<TResult>(string cacheKey, Func<DistributedCacheEntryOptions, Task<TResult?>> valueFactory, int expireSeconds = 60)
{
// Get data from distributed cache
string jsonStr = await distCache.GetStringAsync(cacheKey);
// Not found in cache
if (string.IsNullOrEmpty(jsonStr))
{
var options = CreateOptions(expireSeconds);
TResult? result = await valueFactory(options);
string jsonOfResult = JsonSerializer.Serialize(result,
typeof(TResult));
// Create data and store it in cache, even the data is null,
// we also store. to avoid Cache penetration
await distCache.SetStringAsync(cacheKey, jsonOfResult, options);
return result;
}
else
{
// refresh the expiry
await distCache.RefreshAsync(cacheKey);
return JsonSerializer.Deserialize<TResult>(jsonStr)!;
}
}
In test or develop phase, we could use In-memory to mock distributed function. Instead of registering Redis, we can use:
builder.Services.AddDistributedMemoryCache();
Notice: It is not a true distributed cache, but an in-memory cache that only works within a single instance of an application. It does not provide distributed caching across multiple servers or instances like a real distributed cache(e.g. Redis, NCache, or Memcached) would.
Top comments (0)