Cache introduction
Advantages of caching:
- Improve website access speed
- Applicable to data that is not easy to change
Disadvantages of caching:
- Careful planning
- Strange side effects
Cache location:
- Server (single server)
- Cache server (multi server)
- client
In memory cache
- The simplest
- IMemoryCache
- For Sticky Session
- Applicable to any type of object
Sticky Session: the in memory cache is stored in the memory of the Web server and can only be accessed by this server. When a Web application is deployed on multiple servers, it is necessary to ensure that the server accessed by the user is the server that was cached before.
Through services Addmemorycache(); Enable memory caching in Startup ConfigureServices.
MemoryCacheEntryOptions:
- Absolute expiration time
- Sliding expiration time: after each request to access the cache, the cache expiration time will be reset
- Cache Priority
- PostEvictionDelegate: this delegate is called when the cached data is cleared
Use in memory cache in AlbumController:
// GET: Album public async Task<ActionResult> Index() { if (!_memoryCache.TryGetValue( CacheEntryConstants.AlbumsOfToday, out List<Album> cachedAlbums)) { cachedAlbums = await _albumService.GetAllAsync(); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); cacheEntryOptions.RegisterPostEvictionCallback(FillCache, this); _memoryCache.Set(CacheEntryConstants.AlbumsOfToday, cachedAlbums, cacheEntryOptions); } return View(cachedAlbums); } private void FillCache(object key, object value, EvictionReason reason, object state) { // Not specifically implemented Console.WriteLine("Cache entry is evicted!"); }
Cache Tag Helper
Format:
<cache>@await Component.InvokeAsync("xxx")</cache>
- Server side
- The actual use of IMemoryCache also requires Sticky Session
Properties:
- enabled
- Expires on: absolute expiration time
- expires-after
- expires-sliding
- Vary by header: if the requested header changes, the cache needs to be refreshed
- vary-by-query
- vary-by-route
- vary-by-cookie
- vary-by-user
- vary-by
- priority
Example:
<cache expires-after="@TimeSpan.FromSeconds(30)"> @await Component.InvokeAsync("InternetStatus") </cache>
Distributed cache
Features:
- Sticky Session not required
- Scalable
- Web server restart does not affect cache
- Better performance
Interfaces and common methods:
- IDistributedCache
- Get, GetAsync
- Set, SetAsync
- Refresh, RefreshAsync
- Remove, RemoveAsync
Type:
- Distributed Memory Cache (only suitable for development)
- Distributed Sql Server Cache
- Distributed Redis Cache (recommended)
Redis Cache
Install Redis through Docker: docker pull redis
If the pull speed is slow, it is recommended to use Alibaba cloud image accelerator( Simple tutorial).
Run container: docker run --name my redis -d -p 6379:6379 redis
Name exposed port 6379 image name
docker ps to view the running status:
docker run -it --link my-redis:my-redis --rm redis redis-cli -h my-redis -p 6379
- -it: interactive
- --Link my redis: link to my redis
- : my redis: the name inside is also called my redis
- --rm: delete a container after it is stopped
- Redis: the image is redis
- Redis cli: run the redis cli program
- -H my redis: hostname is my redis
- -p 6379: port 6379
Test redis:
Open NuGet to install Redis:
Configure Redis in Startup:
services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "redis-for-albums"; });
Using Redis in the AlbumController:
private readonly ILogger<AlbumController> _logger; private readonly IDistributedCache _distributedCache; private readonly IAlbumService _albumService; private readonly HtmlEncoder _htmlEncoder; public AlbumController( IAlbumService albumService, HtmlEncoder htmlEncoder, ILogger<AlbumController> logger, IDistributedCache distributedCache) { _albumService = albumService; _htmlEncoder = htmlEncoder; _logger = logger; _distributedCache = distributedCache; } // GET: Album public async Task<ActionResult> Index() { List<Album> cachedAlbums; var cachedAlbumsString = _distributedCache.Get(CacheEntryConstants.AlbumsOfToday); if (cachedAlbumsString == null) { cachedAlbums = await _albumService.GetAllAsync(); var serializedString = JsonConvert.SerializeObject(cachedAlbums); byte[] encodedAlbums = Encoding.UTF8.GetBytes(serializedString); var cacheEntryOptions = new DistributedCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); _distributedCache.Set(CacheEntryConstants.AlbumsOfToday, encodedAlbums, cacheEntryOptions); } else { byte[] encodedAlbums = _distributedCache.Get(CacheEntryConstants.AlbumsOfToday); var serializedString = Encoding.UTF8.GetString(encodedAlbums); cachedAlbums = JsonConvert.DeserializeObject<List<Album>>(serializedString); } return View(cachedAlbums); }
Response cache
- Header based
- Client cache
- Use ResponseCache Attribute
Parameters:
- Location
- Duration
- NoStore
- VaryByHeader
Configure the Response cache when configuring MVC middleware:
services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); options.Filters.Add<LogResourceFilter>(); options.CacheProfiles.Add("Default",new CacheProfile { Duration = 60 }); options.CacheProfiles.Add("Never", new CacheProfile { Location = ResponseCacheLocation.None, NoStore = true }); });
Use of Response cache:
// Manual configuration [ResponseCache(Duration = 30, Location = ResponseCacheLocation.Client)] public IActionResult Index() { _logger.LogInformation(MyLogEventIds.HomePage, "Visiting Home Index ..."); return View(); } // By specifying CacheProfile Configure [ResponseCache(CacheProfileName = "Default")] public IActionResult Privacy() { return View(); }
Note:
- You must open the page with a browser that is not started by VS debugging to test the Response cache effect
- The Response cache does not work when the page is refreshed
- Please refer to the related contents of Response caching Middleware Official documents
compress
Compress the transmitted data. Usually for data above 1K.
services.AddResponseCompression();//Register compression service
app.UseResponseCompression();
Refer to official documents for details: Response compression in ASP.NET Core.