About me
The author blog | start
Caching basics
Caching can significantly improve application performance and scalability by reducing the effort required to generate content. Caching works best for data that doesn’t change often and is expensive to generate. With caching, it is possible to make a much faster copy of the data returned from the data source. Applications should be written and tested so that they never rely on cached data.
ASP.NET Core supports multiple different caches. The simplest cache is based on IMemoryCache. IMemoryCache represents the cache stored in the memory of the Web server. Applications running on a server farm (multiple servers) should ensure that sessions are stuck while using in-memory caches. Sticky sessions ensure that subsequent requests from clients are sent to the same server.
An in-memory cache can store any object. The distributed cache interface is limited to byte[]. In-memory and distributed caches use cached items as key-value pairs.
Cache guide
- Code should always have fallback options to retrieve data, rather than relying on available cache values.
- Caches use rare resource memory to limit cache growth:
- Do not use external inputs as cache keys.
- Use expiration to limit cache growth.
- Limit the cache Size using SetSize, Size, and SizeLimit]. The ASP.NET Core runtime does not limit the cache size based on memory pressure. Developers need to limit the cache size.
use
DI injection
Create a NetCore console project to demonstrate the caching project.
The console project has only one initialized program.cs file. Each step of coding projects based on NetCore is to create a basic template using dependency injection.
nuget install Microsoft.Extensions.Hosting
Copy the code
public static class Program { static async void Main(string[] args) { var builder = new HostBuilder().ConfigureServices((context, service) => { }); await builder.RunConsoleAsync(); }}Copy the code
Into the cache service, console library need to download the Microsoft Extensions. Caching. The Memory
nuget install Microsoft.Extensions.Caching.Memory
Copy the code
public static class Program { static async void Main(string[] args) { var builder = new HostBuilder().ConfigureServices((context, service) => { service.AddMemoryCache(); service.AddScoped<CacheService>(); // The actual test service service.addhostedService <BackgroundJob>(); }); await builder.RunConsoleAsync(); }}Copy the code
Background services
public class BackgroundJob : IHostedService { private readonly CacheService _cacheService; public BackgroundJob(CacheService cacheService) { _cacheService = cacheService; } public Task StartAsync(CancellationToken cancellationToken) { _cacheService.Action(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; }}Copy the code
Summary of MemoryCache usage
IMemoryCache is automatically injected through the constructor
public class CacheService { private readonly IMemoryCache _memoryCache; public CacheService(IMemoryCache memoryCache) { _memoryCache = memoryCache; }}Copy the code
The most basic use
The Set method sets the cache based on the Key. The default cache does not expire
The Get method fetches the cache based on the Key
/// </summary> public void BaseCache() {string cacheKey = "timestamp"; // </summary> public void BaseCache() {string cacheKey = "timestamp"; //set cache _memoryCache.Set(cacheKey, DateTime.Now.ToString()); //get cache Console.WriteLine(_memoryCache.Get(cacheKey)); }Copy the code
IMemoryCache provides some good syntax candy for developers to use, see the documentation below
/// </summary> public void ActionUse() {// Scenario - If the cache exists, remove it. If the cache does not exist, write // primitive string cacheKey = "timestamp"; if (_memoryCache.Get(cacheKey) ! = null) { _memoryCache.Set(cacheKey, DateTime.Now.ToString()); } else { Console.WriteLine(_memoryCache.Get(cacheKey)); Var dataCacheValue = _memoryCache.getorCreate (cacheKey, entry => {return datetime.now.tostring (); }); Console.WriteLine(dataCacheValue); _memorycache. Remove(cacheKey); _memoryCache.TryGetValue(cacheKey, out string cacheValue); Console.WriteLine(cacheValue); }Copy the code
Cache expiration policy
There are two common ways to set the cache
- Absolute maturity (specified to expire at a fixed point in time)
- Slide expiration (expires if not hit for a length of time)
- Combination expiration (absolute expiration + sliding expiration)
Absolute maturity
Expiration Policy expires in 5 seconds
//set absolute cache
string cacheKey = "absoluteKey";
_memoryCache.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromSeconds(5));
//get absolute cache
for (int i = 0; i < 6; i++)
{
Console.WriteLine(_memoryCache.Get(cacheKey));
Thread.Sleep(1000);
}
Copy the code
Sliding due
Expiration policy Sliding expiration time of 2 seconds. If there is access within 2 seconds, the expiration time is delayed. When there is no access within the 2-second interval, the cache expires
//set slibing cache
string cacheSlibingKey = "slibingKey";
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
options.SlidingExpiration = TimeSpan.FromSeconds(2);
_memoryCache.Set(cacheSlibingKey, DateTime.Now.ToString(), options);
//get slibing cache
for (int i = 0; i < 2; i++)
{
Console.WriteLine(_memoryCache.Get(cacheSlibingKey));
Thread.Sleep(1000);
}
for (int i = 0; i < 2; i++)
{
Thread.Sleep(2000);
Console.WriteLine(_memoryCache.Get(cacheSlibingKey));
}
Copy the code
Combination of overdue
Expiry policies
6 seconds absolute expiration +2 seconds sliding expiration
Any of these caches will be invalidated
string cacheCombineKey = "combineKey";
MemoryCacheEntryOptions combineOptions = new MemoryCacheEntryOptions();
combineOptions.SlidingExpiration = TimeSpan.FromSeconds(2);
combineOptions.AbsoluteExpiration = DateTime.Now.AddSeconds(6);
_memoryCache.Set(cacheCombineKey, DateTime.Now.ToString(), combineOptions);
//get slibing cache
for (int i = 0; i < 2; i++)
{
Console.WriteLine(_memoryCache.Get(cacheCombineKey));
Thread.Sleep(1000);
}
for (int i = 0; i < 6; i++)
{
Thread.Sleep(2000);
Console.WriteLine(i+"|" + _memoryCache.Get(cacheCombineKey));
}
Console.WriteLine("------------combineKey End----------------");
Copy the code
Caches state change events
When the cache is updated or deleted, a callback event is triggered to record the cache changes.
/// <summary> /// cache status change callback /// </summary> public void CacheStateCallback() {MemoryCacheEntryOptions options = new MemoryCacheEntryOptions(); options.AbsoluteExpiration = DateTime.Now.AddSeconds(3 ); options.RegisterPostEvictionCallback(MyCallback, this); //show callback console string cacheKey = "absoluteKey"; _memoryCache.Set(cacheKey, DateTime.Now.ToString(), options); Thread.Sleep(500); _memoryCache.Set(cacheKey, DateTime.Now.ToString(), options); _memoryCache.Remove(cacheKey); } private static void MyCallback(object key, object value, EvictionReason reason, object state) { var message = $"Cache entry state change:{key} {value} {reason} {state}"; ((CacheService)state)._memoryCache.Set("callbackMessage", message); Console.WriteLine(message); }Copy the code
Cache dependency policy
Set A cache A Set A cache B, depending on cache A if cache A fails, cache B fails
</ / </summary> public void CacheDependencyPolicy() {string DependentCTS = "DependentCTS"; string cacheKeyParent = "CacheKeys.Parent"; string cacheKeyChild = "CacheKeys.Child"; var cts = new CancellationTokenSource(); _memoryCache.Set(DependentCTS, cts); Using (var Entry = _memoryCache.createEntry (cacheKeyParent)) {// The current key Value entry.Value = "parent" + DateTime.Now; / / the current key corresponding to the callback event entry. RegisterPostEvictionCallback (MyCallback, this); _memoryCache.Set(cacheKeyChild, "child" + datetime. Now, new CancellationChangeToken(cts.token)); } string ParentCachedTime = _memoryCache.Get<string>(cacheKeyParent); string ChildCachedTime = _memoryCache.Get<string>(cacheKeyChild); string callBackMsg = _memoryCache.Get<string>("callbackMessage"); Console.WriteLine(" First fetch "); Console.WriteLine(ParentCachedTime + "|" + ChildCachedTime + "|" + callBackMsg); ParentKey _memoryCache.Get<CancellationTokenSource>(DependentCTS).cancel (); Thread.Sleep(1000); ParentCachedTime = _memoryCache.Get<string>(cacheKeyParent); ChildCachedTime = _memoryCache.Get<string>(cacheKeyChild); callBackMsg = _memoryCache.Get<string>("callbackMessage"); Console.WriteLine(" Second fetch "); Console.WriteLine(ParentCachedTime + "|" + ChildCachedTime + "|" + callBackMsg); }Copy the code
The resources
Cache memory in AspNetCore
. MemoryCache for NetCore cache
Asp.Net Core easy to learn – in. Net Core uses caching and configure dependency policies
[Embrace.net Core Series: MemoryCache Expiration]