当前位置: 移动技术网 > IT编程>开发语言>.net > Asp.Net Core 轻松学-在.Net Core 使用缓存和配置依赖策略

Asp.Net Core 轻松学-在.Net Core 使用缓存和配置依赖策略

2018年12月20日  | 移动技术网IT编程  | 我要评论

完美搭档下载,救助犬格莱特,rapture3d

前言

    几乎在所有的应用程序中,缓存都是一个永恒的话题,恰当的使用缓存可以有效提高应用程序的性能;在某些业务场景下,使用缓存依赖会有很好的体验;在 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<ienumerable<string>> get()
        {
            cache.set("userid", "0001");
            return new string[] { "value1", "value2" };
        }

        [httpget("{id}")]
        public actionresult<string> get(int id)
        {
            return cache.get<string>("userid");
        }
    }

上面的代码表示在 homecontroller 控制器的构造方法中使用注入的方式获得了一个 imemorycache 对象,在 get() 方法中增加了一条缓存记录 "userid=0001",然后在 get(int id) 接口中提取该缓存记录
运行程序,分别调用 get() 和 get(int id) 接口,获得下面的输出信息

  • 调用 get() 接口

  • 调用 get(int id) 接口

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

2. 应用缓存策略

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

2.1 memorycacheoptions 配置,memorycacheoptions的配置项目不多,看下面的代码
    public class memorycacheoptions : ioptions<memorycacheoptions>
    {
        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<ienumerable<string>> 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<string> 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<string>(cachekeys.usersession),
                usersharedata = cache.get<string>(cachekeys.usersharedata),
                usercart = cache.get<string>(cachekeys.usercart)
            };

            return new jsonresult(userinfo);
        }

        // 移除缓存
        [httppost("logout")]
        public actionresult<string> logout()
        {
            cache.get<cancellationtokensource>(cachekeys.dependentcts).cancel();

             var userinfo = new
            {
                usersession = cache.get<string>(cachekeys.usersession),
                usersharedata = cache.get<string>(cachekeys.usersharedata),
                usercart = cache.get<string>(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 登录后注册依赖

  • getkeys 获取缓存

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

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

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

结束语

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

示例代码下载

https://files.cnblogs.com/files/viter/ron.memorycachedemo.zip

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网