ASP.NET Core 中的缓存 / MemoryCache

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

ASP.NET Core 缓存Caching,.NET Core 中为我们提供了Caching 的组件。

目前Caching 组件提供了三种存储方式。

Memory

Redis

SqlServer

学习在ASP.NET Core 中使用Caching。

Memory Caching

1.新建一个 ASP.NET Core 项目,选择Web 应用程序,将身份验证 改为 不进行身份验证。

2.添加引用

Install-Package Microsoft.Extensions.Caching.Memory

3.使用

在Startup.cs 中 ConfigureServices

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMemoryCache();
            // Add framework services.
            services.AddMvc();            
        }

然后在控制器中依赖注入、

        private IMemoryCache _cache;

        public LongLongController(IMemoryCache memoryCache)
        {
            _cache = memoryCache;
        }

1、方法:TryGetValue 及 方法缓存的存取

        public IActionResult Index()
        {
            string cacheKey_2 = "CacheKey";
            List<string> cacheEntry;
            //如果缓存没有过期,则Out测试就是缓存存储的值,注意存放值的类型应该和Out参数一致。
            var bol = _cache.TryGetValue<List<string>>(cacheKey_2, out cacheEntry);
            //判断缓存是否存在
            if (!bol)
            {
                List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                 .SetSlidingExpiration(TimeSpan.FromMinutes(10));
                _cache.Set(cacheKey_2, lst, cacheEntryOptions);
            }
            ViewBag.cacheEntry = _cache.Get(cacheKey_2);
            return View();
        }

在TryGetValue 中,Out 参数的类型应与缓存中存储的值的类型一致。否则TryGetValue 中的Out参数永远为NULL。

2、设置缓存的过期时间,可采用绝对过期时间或相对过期时间两种模式;

相对过期时间设置方式:

var cacheEntryOptions = new MemoryCacheEntryOptions()
                 .SetSlidingExpiration(TimeSpan.FromSeconds(10));

代码如下:

        /// <summary>
        /// 相对过期时间十秒 如果:十秒内不间断有人访问,那么在访问期间缓存不会消失。除非前后访问时间大于十秒,缓存会消失
        /// </summary>
        /// <returns></returns>
        public IActionResult Slid()
        {
            string cacheKey_2 = "SlidCache";
            List<string> cacheEntry;
            var bol = _cache.TryGetValue<List<string>>(cacheKey_2, out cacheEntry);
            //判断缓存是否存在
            if (!bol)
            {
                List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                 .SetSlidingExpiration(TimeSpan.FromSeconds(10));
                _cache.Set(cacheKey_2, lst, cacheEntryOptions);
            }
            ViewBag.cacheEntry = _cache.Get(cacheKey_2);
            return View();
        }
View Code

注意上述代码中的备注;假设我们设置一个缓存的相对过期时间为10秒,缓存由A创建,十秒中内,B进入可系统,并读取了缓存,这时缓存的有效时间又会变成十秒,同理,只要缓存在十秒钟内不间断有其他人访问,则缓存永远不会过期。如果大于十秒,则缓存过期。

绝对过期时间设置方式:

 var cacheEntryOptions = new MemoryCacheEntryOptions()
                 .SetAbsoluteExpiration(TimeSpan.FromSeconds(10));

代码如下:

        /// <summary>
        /// 绝对过期时间 10秒
        /// </summary>
        /// <returns></returns>
        public IActionResult Abs()
        {
            string cacheKey_2 = "SlidCache";
            List<string> cacheEntry;
            var bol = _cache.TryGetValue<List<string>>(cacheKey_2, out cacheEntry);
            //判断缓存是否存在
            if (!bol)
            {
                List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                 .SetAbsoluteExpiration(TimeSpan.FromSeconds(10));
                _cache.Set(cacheKey_2, lst, cacheEntryOptions);
            }
            ViewBag.cacheEntry = _cache.Get(cacheKey_2);
            return View();
        }
View Code

绝对过期时间不管期间有没有人访问,在时间过后,就会过期,清空。

3、移除缓存

_cache.Remove(cacheKey_2);

移除缓存没什么好说的,就是把缓存清空

代码如下:

        /// <summary>
        /// 测试移除缓存
        /// </summary>
        /// <returns></returns>
        public IActionResult Remove()
        {
            //先添加缓存
            string cacheKey_2 = "RemoveCache";
            List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
            var cacheEntryOptions = new MemoryCacheEntryOptions()
             .SetAbsoluteExpiration(TimeSpan.FromHours(10));
            _cache.Set(cacheKey_2, lst, cacheEntryOptions);

            //直接移除
            _cache.Remove(cacheKey_2);
            return View();
        }
View Code

4、缓存的优先级分为四种:永不过期  大于  高优先级  大于  一般优先级  大于  低优先级。

/缓存优先级 (程序压力大时,会根据优先级自动回收)

 永不过期:

            var cacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.NeverRemove);

高优先级:

 var HighCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.High);

一般优先级:

 var NormalCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.Normal);

低优先级:

 var LowCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.Low);

代码如下:

        /// <summary>
        /// 缓存优先级
        /// </summary>
        /// <returns></returns>
        public IActionResult CacheLevel()
        {
            List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
            //NeverRemove 最高优先级 永远不会过期
            string NeverRemove = "NeverRemove";
            var cacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.NeverRemove);
            _cache.Set(NeverRemove, lst, cacheEntryOptions);
            //
            //High 高优先级 永远不会过期
            string High = "High";
            var HighCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.High);
            _cache.Set(High, lst, cacheEntryOptions);
            //Normal 一般的优先级 永远不会过期
            string Normal = "Normal";
            var NormalCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.Normal);
            _cache.Set(Normal, lst, cacheEntryOptions);

            //Normal 一般的优先级 永远不会过期
            string Low = "Low";
            var LowCacheEntryOptions = new MemoryCacheEntryOptions()
             .SetPriority(CacheItemPriority.Low);
            _cache.Set(Low, lst, cacheEntryOptions);
            return View();
        }
View Code

5、缓存过期后,执行回调函数,

            _cache.Set(cacheKey, lst, new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromSeconds(10))
                .RegisterPostEvictionCallback((key, value, reason, substate) =>
                {
                    //调用回调函数
                    GetIntList(key,value,reason,substate);
                }));

代码如下:

        public IActionResult cacheCallback()
        {
            List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
            //缓存回调 10秒过期会回调
            string cacheKey = "cacheKey";
            _cache.Set(cacheKey, lst, new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromSeconds(10))
                .RegisterPostEvictionCallback((key, value, reason, substate) =>
                {
                    //调用回调函数
                    GetIntList(key,value,reason,substate);
                }));
            //
            return View();
        }
        public void GetIntList(object key,object value, object reason, object substate)
        {
            List<string> lst=(List<string>)value;
            //说白了就是被释放了
            Console.WriteLine($"键{key}的缓存因:{reason}而改变。");
            foreach(var item in lst)
            {
                Console.WriteLine(item);
            }
        }
View Code

6、缓存回调 根据Token过期

 var cts = new CancellationTokenSource();
            _cache.Set(cacheKey, lst, new MemoryCacheEntryOptions()
                .AddExpirationToken(new CancellationChangeToken(cts.Token))
                .RegisterPostEvictionCallback((key, value, reason, substate) =>
                {
                    Console.WriteLine($"键{key}值{value}改变,因为{reason}");
                }));
            cts.Cancel(); //执行到Cancel()方法时,会执行回调删除

代码如下:

        public ActionResult CacheToken()
        {
            List<string> lst = new List<string>() { "陈大六", "陈卧龙", "陈新宇", "刘丽", "花国锋" };
            string cacheKey = "CacheToken";
            //缓存回调 根据Token过期
            var cts = new CancellationTokenSource();
            _cache.Set(cacheKey, lst, new MemoryCacheEntryOptions()
                .AddExpirationToken(new CancellationChangeToken(cts.Token))
                .RegisterPostEvictionCallback((key, value, reason, substate) =>
                {
                    Console.WriteLine($"键{key}值{value}改变,因为{reason}");
                }));
            cts.Cancel(); //执行到Cancel()方法时,会执行回调删除
            return View();
        }
View Code

7、页面缓存、distributed-cache

Cshtml页面代码如下:

<distributed-cache name="mycache" expires-after="TimeSpan.FromSeconds(10)">
    <p>缓存项10秒过期-LineZero</p>
    @DateTime.Now
</distributed-cache>
<distributed-cache name="mycachenew" expires-sliding="TimeSpan.FromSeconds(10)">
    <p>缓存项有人访问就不会过期,无人访问10秒过期-LineZero</p>
    @DateTime.Now
</distributed-cache>

这样就能缓存标签内的内容。

如果你觉得本文对你有帮助,请点击“推荐”,谢谢。

@陈卧龙的博客

原文地址:https://www.cnblogs.com/chenwolong/p/MemoryCache.html