博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.Net Core 轻松学-在.Net Core 使用缓存和配置依赖策略
阅读量:5880 次
发布时间:2019-06-19

本文共 6292 字,大约阅读时间需要 20 分钟。

原文:

前言

    几乎在所有的应用程序中,缓存都是一个永恒的话题,恰当的使用缓存可以有效提高应用程序的性能;在某些业务场景下,使用缓存依赖会有很好的体验;在 Asp.Net Core 中,支持了多种缓存组件,这其中最基础也最易用的当属 IMemoryCache,该接口表示其存储依赖于托管程序服务器的内存,下面要介绍的内容就是基于 IMemoryCache 的缓存依赖。

1. IMemoryCache 的实现

Asp.Net Core 内部实现了一个继承自 IMemoryCache 接口的类 MemoryCache

这几乎已成惯例,一旦某个接口被列入 SDK 中,其必然包含了一个默认实现

1.1 使用 IMemoryCache

在 Asp.Net Core 中要使用 IMemoryCache 非常简单,只需要在 Startup 的 ConfigureServices 方法加入一句代码 services.AddMemoryCache() 即可

public void ConfigureServices(IServiceCollection services)        {            services.AddMemoryCache();            ...        }
1.2 在控制器中使用 IMemoryCache
[Route("api/[controller]")]    [ApiController]    public class HomeController : ControllerBase    {        private IMemoryCache cache;        public HomeController(IMemoryCache cache)        {            this.cache = cache;        }        [HttpGet]        public ActionResult
> Get() { cache.Set("userId", "0001"); return new string[] { "value1", "value2" }; } [HttpGet("{id}")] public ActionResult
Get(int id) { return cache.Get
("userId"); } }

上面的代码表示在 HomeController 控制器的构造方法中使用注入的方式获得了一个 IMemoryCache 对象,在 Get() 方法中增加了一条缓存记录 "userId=0001",然后在 Get(int id) 接口中提取该缓存记录

运行程序,分别调用 Get() 和 Get(int id) 接口,获得下面的输出信息

  • 调用 Get() 接口

26882-20181219213933322-28613642.png

  • 调用 Get(int id) 接口

26882-20181219214031396-446632914.png

这看起来非常容易,几乎不用什么思考,你就学会了在 Asp.Net Core 中使用缓存,容易使用,这非常重要,这也是一门语言广泛推广的根本态度

2. 应用缓存策略

IMemoryCache 还包含了一个带参数的构造方法,让我们可以对缓存进行灵活的配置,该配置由类 MemoryCacheOptions 决定

2.1 MemoryCacheOptions 配置,MemoryCacheOptions的配置项目不多,看下面的代码
public class MemoryCacheOptions : IOptions
{ public MemoryCacheOptions(); public ISystemClock Clock { get; set; } [Obsolete("This is obsolete and will be removed in a future version.")] public bool CompactOnMemoryPressure { get; set; } public TimeSpan ExpirationScanFrequency { get; set; } public long? SizeLimit { get; set; } public double CompactionPercentage { get; set; } }
  • ISystemClock:系统时钟,默认值为 null,官方文档对此属性没有说明,我也不知道是干什么用的,哪位大神求告知其作用和原理
  • ExpirationScanFrequency:对过期缓存的扫描间隔时间
  • SizeLimit:缓存区可存储记录条目数量
  • CompactionPercentage:在缓存过期策略生效的时候,对缓存进行压缩的百分比

上面的这个配置非常简单,在系统中应用类似下面的代码这样

public void ConfigureServices(IServiceCollection services)        {            services.AddMemoryCache(options =>            {                options.CompactionPercentage = 0.02d;                options.ExpirationScanFrequency = TimeSpan.FromMinutes(5);                options.SizeLimit = 1024;            });            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);        }

上面的缓存策略设置为缓存压缩比为 2%,每 5 分钟进行一次过期缓存的扫描,最大缓存空间大小限制为 1024

使用方法不变

2.1 单个键缓存策略

由于缓存的所有键其缓存过期优先级都是默认的 Normal,可能我们需要在某些业务场景下,让某些缓存值设置一个较高的优先级,比如设置永远都不过期,这样即使缓存达到最大限制条数以后也不会对其进行清理

  • 缓存优先级,该值为一个枚举类型,分别是 低、普通、高、永不移除,开发者可以根据不同的业务场景灵活设置
public enum CacheItemPriority    {        Low = 0,        Normal = 1,        High = 2,        NeverRemove = 3    }
  • 设置策略,下面就使用 MemoryCacheEntryOptions 对单个键值进行应用策略
[HttpGet]        public ActionResult
> Get() { MemoryCacheEntryOptions entry = new MemoryCacheEntryOptions { Priority = CacheItemPriority.NeverRemove }; cache.Set("userId", "0001", entry); return new string[] { "value1", "value2" }; }

上面的代码表示,我们对缓存键 "userId" 应用了一个 “永不移除” 的策略,当然,还可以对单个值做非常多的策略,比如现在 "userId" 的值大小等等,有兴趣的同学可以深入了解 MemoryCacheEntryOptions 类

3. 使用缓存依赖策略

缓存依赖的意思是表示,一个或者多个缓存依赖于某个缓存,当某个缓存过期的时候,对其有依赖条件的其它缓存也会过期,在某些应用场景下,缓存依赖非常有用

3.1 创建 TokenController 并登录后注册依赖、获取缓存、移除缓存接口

以下示例使用一个模拟用户登录/登出的业务场景

[Route("api/[controller]")]    [ApiController]    public class TokenController : ControllerBase    {        private IMemoryCache cache;        public TokenController(IMemoryCache cache)        {            this.cache = cache;        }        // 创建注册依赖        [HttpGet("login")]        public ActionResult
Login() { var cts = new CancellationTokenSource(); cache.Set(CacheKeys.DependentCTS, cts); using (var entry = cache.CreateEntry(CacheKeys.UserSession)) { entry.Value = "_x0123456789"; entry.RegisterPostEvictionCallback(DependentEvictionCallback, this); cache.Set(CacheKeys.UserShareData, "这里是共享的数据", new CancellationChangeToken(cts.Token)); cache.Set(CacheKeys.UserCart, "这里是购物车", new CancellationChangeToken(cts.Token)); } return "设置依赖完成"; } // 获取缓存 [HttpPost("getkeys")] public IActionResult GetKeys() { var userInfo = new { UserSession = cache.Get
(CacheKeys.UserSession), UserShareData = cache.Get
(CacheKeys.UserShareData), UserCart = cache.Get
(CacheKeys.UserCart) }; return new JsonResult(userInfo); } // 移除缓存 [HttpPost("logout")] public ActionResult
LogOut() { cache.Get
(CacheKeys.DependentCTS).Cancel(); var userInfo = new { UserSession = cache.Get
(CacheKeys.UserSession), UserShareData = cache.Get
(CacheKeys.UserShareData), UserCart = cache.Get
(CacheKeys.UserCart) }; return new JsonResult(userInfo); } // 过期通知 private static void DependentEvictionCallback(object key, object value, EvictionReason reason, object state) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Key:{0} 已过期,依赖于该 Key 的所有缓存都将过期而处于不可用状态", key); Console.ForegroundColor = ConsoleColor.Gray; } }

上面的代码使用 CancellationTokenSource 用作事件通知源,当移除 CacheKeys.DependentCTS 并触发 CancellationTokenSource.Cancel() 方法后,将异步触发 DependentEvictionCallback(object key, object value, EvictionReason reason, object state)委托;此时,托管程序收到一个通知,用户已登出,已移除用户相关缓存,任何移除接口尝试再次读取 CacheKeys 项,此时,返回值为空

3.2 运行程序,分别调用 login/getkeys/logout 接口,分别得到以下输出结果
  • login 登录后注册依赖

26882-20181219214041954-786773046.png

  • getkeys 获取缓存

26882-20181219214048672-1849044752.png

  • logout 移除缓存,尝试再次读取 CacheKeys 项,此时,返回值为空

26882-20181219214057532-2110882983.png

  • 控制台输出移除通知(黄色字体部分信息)

26882-20181219214103378-925251948.png

可以看到,在用户登录登出这个业务场景下,使用缓存依赖项对其相关缓存进行管理,还是非常方便的,当用户退出登录后,即清空其所有相关缓存

结束语

  • 本文通过实例介绍了 IMemoryCache 的简单使用方法
  • 针对单个缓存键,也可以对其进行应用策略
  • 通过使用缓存依赖策略,可以在某些业务场景中有非常好的应用体验
  • 注意:当使用全局缓存策略 SizeLimit 时,每个键都需要设置一个大小
  • IMemoryCache 依赖于托管服务器等内存,一旦重启,缓存数据将立即被释放

示例代码下载

转载地址:http://fodix.baihongyu.com/

你可能感兴趣的文章
服务器的svnserver修改密码
查看>>
利用 fdisk进行分区
查看>>
WPF 实现窗体拖动
查看>>
来自维基百科程序员Brandon Harris
查看>>
NULL不是数值
查看>>
CentOS 5 全功能WWW服务器搭建全教程
查看>>
30个优秀的后台管理界面设计案例分享
查看>>
scala111
查看>>
模块化服务规范——OSGI
查看>>
劣质代码评析——猜数字问题(上)
查看>>
纸上谈兵: 栈 (stack)
查看>>
Windows phone8 基础篇(三) 常用控件开发
查看>>
Oracle学习笔记之五,Oracle 11g的PL/SQL入门
查看>>
PHP安全编程:register_globals的安全性 全局变量注册(转)
查看>>
工程技巧Linux上建立工程项目
查看>>
Linux php 中文乱码解决
查看>>
pjsip视频通信开发(上层应用)之拨号键盘下部份拨号和删除功能
查看>>
SAP-GR/IR的理解
查看>>
Web自动化测试 Selenium 3/3 https的配置
查看>>
.NET 常用加密、解密& 数字签名算法
查看>>