缓存
缓存的优点
- 提高网站的访问速度
- 适用 于不易改变的数据
缓存的位置
- 服务器端(Web服务器 In-Memory 内存缓存)
- 缓存服务器(集群服务器)
- 客户端
一、In-Memory 内存缓存(存在于Web服务器,仅能在一个服务器上使用)
- 最简单的
- IMemoryCache
- 适用 于Sticky Session(粘性会话)
- 适用 于任何类型的对象
//首先注册服务器内存缓存 builder.Services.AddMemoryCache();
设置缓存
public class MoviesController : Controller { private readonly MvcMovieContext _context; private readonly IMemoryCache m_MemoryCache; public MoviesController(MvcMovieContext context, IMemoryCache memoryCache) { _context = context; m_MemoryCache = memoryCache; } public async Task<IActionResult> List() { //判断是否在缓存中 if (!m_MemoryCache.TryGetValue(CacheKeyValue.Movies , out List<Movie> cachedMovies)) { cachedMovies = await _context.Movie.ToListAsync(); //设置缓存过期时间 var cacheEntryOptions = new MemoryCacheEntryOptions() //.SetAbsoluteExpiration(TimeSpan.FromSeconds(600))//绝对过期时间 .SetSlidingExpiration(TimeSpan.FromSeconds(30));//相对活跃时间的滚动过期时间 //回调函数,即缓存被清除之后调用 cacheEntryOptions.RegisterPostEvictionCallback(FillCache, this); //设置缓存的值 m_MemoryCache.Set(CacheKeyValue.Movies, cachedMovies, cacheEntryOptions); } return View(cachedMovies); } }
二、 Cache Tag Helper 缓存组件
使用方法:
<cache expires-after="@TimeSpan.FromSeconds(30)"> @await Component.InvokeAsync("xxViewComponent") </cache>
缓存在服务器端,实际上是使用的 IMemoryCache
三、分布式缓存(例如:Redis Cache)
特点:
- 无需 Sticky Session
- 可扩展
- 服务器重启不会影响缓存
- 性能更好
微软提供的分布式缓存接口 IDistributedCache ,存储的数据类型为:byte[ ]
缓存使用的方法如下:
- Get,GetAsync
- Set,SetAsync
- Refresh,RefreshAsync
- Remove,RemoveAsync
通过NuGet引用 Microsoft.Extensions.Caching.Redis 程序包
//注册Redis分布式缓存服务 builder.Services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "movies"; });
使用Redis缓存
public class MoviesController : Controller { private readonly MvcMovieContext _context; private readonly IMemoryCache m_MemoryCache; private readonly IDistributedCache m_DistributedCache; public MoviesController(MvcMovieContext context, IMemoryCache memoryCache, IDistributedCache distributedCache) { _context = context; m_MemoryCache = memoryCache; m_DistributedCache = distributedCache; } public async Task<IActionResult> List() {//Redis缓存 List<Movie> cachedMovies = null; var cacheMovieString = await m_DistributedCache.GetStringAsync(CacheKeyValue.Movies); if (cacheMovieString == null) {//缓存不存在 cachedMovies = await _context.Movie.ToListAsync(); //设置缓存 var serializedString = JsonSerializer.Serialize(cachedMovies);//序列化为字符串 //byte[] encodeMovies = Encoding.UTF8.GetBytes(serializedString); var cacheEntryOptions = new DistributedCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); await m_DistributedCache.SetStringAsync(CacheKeyValue.Movies, serializedString, cacheEntryOptions); } else {//读取缓存 cachedMovies = JsonSerializer.Deserialize<List<Movie>>(cacheMovieString, new JsonSerializerOptions()); } return View(cachedMovies); } }
四、客户端缓存 Response 缓存
- 基于 Header
- 客户端缓存
- 使用 ResponseCache 这个Attribute
Response 缓存参数
- Location 缓存放在那
- Duration 缓存时间长短
- NoStore 不缓存
- VaryByHeader 通过检测 Header 的值来判断是否使用缓存。
builder.Services.AddControllersWithViews(options => { options.CacheProfiles.Add("Default", new CacheProfile {//设置Response缓存 Duration = 60 }); });
//方法1:直接写缓存参数 //[ResponseCache(Duration =30,Location = ResponseCacheLocation.Client)] //方法2(推荐):使用Program.cs 配置文件中的缓存参数 [ResponseCache(CacheProfileName="Default")] public async Task<IActionResult> List() { //... }
五、压缩
压缩传输的数据
//压缩传输数据 builder.Services.AddResponseCompression(); var app = builder.Build(); app.UseResponseCompression();//默认使用 gzip