Cache(缓存)是优化web应用的常用方法,缓存存放在服务端的内存中,被所有用户共享。由于Cache存放在服务器的内存中,所以用户获取缓存资源的速度远比从服务器硬盘中获取快,但是从资源占有的角度考虑缓存也不是越多越好。经常要用到且不会频繁改变且被用户共享的数据很适合放在缓存中。在介绍netcore的缓存前我们先回顾下net framework中的缓存技术。

  net framework中常用的缓存有两种: System.Runtime.Caching 和 System.Web.Caching

1 Net Framewoke的缓存

1.1 System.Web.Caching

  System.Web.Caching应该是我们最熟悉的缓存类库了,做ASP.NET开发时用到缓存基本都是使用的这个缓存组件,简单回顾一下用法吧

using System.Web;
using System.Web.Caching; namespace FrameCache
{
class Program
{
static void Main(string[] args)
{
//1.简单缓存,value可以是任何类型
HttpRuntime.Cache.Insert("mykey", "myvalue");
Console.WriteLine($"Key为mykey的缓存:{HttpRuntime.Cache["mykey"]}");

//2.使用缓存依赖项
string path = Path.Combine(Environment.CurrentDirectory, @"someCacheData.xml");
DataSet ds = new DataSet();
ds.ReadXml(path);
if (HttpRuntime.Cache.Get("myxml") == null)
{
//Dataset添加到缓存
System.Web.HttpRuntime.Cache.Insert("myxml", ds, new CacheDependency(path));
}
//从缓存中获取Dataset
DataSet resultDs = (DataSet)HttpRuntime.Cache.Get("myxml");
Console.WriteLine($"food下的f1节点:{resultDs.Tables["food"].Rows[0]["f1"]}");
Console.ReadKey();
}
}
}

  简单的缓存就不说了,添加一下key和value就可以,缓存依赖项CacheDependency是更新缓存的重要手段,但缓存依赖项发生变化时缓存就会被清理。上边栗子中缓存只依赖一个文件,当缓存依赖多个文件时可以这样设置:  CacheDependency cdp=new CacheDependency(new string []{"111.xml","222.xml"}); 。栗子中someCacheData.xml中的内容是:

<?xml version="1.0" encoding="utf-8" ?>
<MyCache>
<animals>
<a1>cat</a1>
<a2>dog</a2>
</animals>
<food>
<f1>apple</f1>
<f2>pear</f2>
</food>
</MyCache>

运行程序结果如下:

1.2 System.Runtime.Caching

  Net Framework中的MemoryCache类就是来自于这个类库,也是开发中经常用到的类库,net core中的缓存用法和这个类库十分相似。简单看一下用法吧

using System.Runtime.Caching;
namespace FrameCache
{
class Program
{
static void Main(string[] args)
{
//缓存的配置
CacheItemPolicy policy = new CacheItemPolicy()
{
//缓存被删除是的回调
RemovedCallback = (arguments) => { Console.WriteLine($"缓存被移除的原因:{arguments.RemovedReason}"); },
//滑动过期时间
SlidingExpiration = TimeSpan.FromSeconds(),
//绝对过期时间
//AbsoluteExpiration = DateTime.Now.AddSeconds(5),
//优先级有两种:Default,NotRemovable(不可移除)
Priority = System.Runtime.Caching.CacheItemPriority.NotRemovable
}; //添加缓存,key为mykey,值是myvalue ,
System.Runtime.Caching.MemoryCache.Default.Add("mykey", "myvalue", policy);
Thread.Sleep();
Console.WriteLine(MemoryCache.Default.Get("mykey"));
Console.ReadKey();
}
}
}
  CacheItemPolicy 对象用于对缓存项做一个设置,如设置绝对/滑动过期时间,优先级,缓存被清理时的回调函数等。程序运行结果如下,如果我们把线程休眠的代码注释掉,则输出为 “myvlaue”。

2 Net core的缓存介绍

  netcore中的缓存用户和 System.Runtime.Caching 很相似,但是在功能上做了增强:缓存的key可以支持object类型(.netframework中缓存key只支持string);提供了泛型支持;可以对缓存和单个缓存项的大小做限定,可以设定缓存的压缩比例(如缓存最大设置为100M,压缩比例为0.2,那么缓存达到一百兆时会清除20M的缓存数据,清除时优先级低的缓存项会被优先清除);此外微软提供了Sqlserver和Redis的缓存支持,可以让我们更方便地实现分布式缓存。

2.1 MemoryCache

1.过期时间  

netcore中缓存相关的类库都在 Microsoft.Extensions.Caching ,使用MemoryCache首先安装包

Install-Package Microsoft.Extensions.Caching.Memory

使用的方式和基本一样,我们简单看一下代码

using Microsoft.Extensions.Caching.Memory;
namespace CacheDemo
{
class Program
{
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { });
//1.最简单使用方式
memoryCache.Set("mykey", "myvalue"); //2.绝对过期时间,3秒后过期
memoryCache.Set("key1", "value1", new DateTimeOffset(DateTime.Now.AddSeconds()));
//3.绝对过期时间,效果同上
memoryCache.Set("key2", "value2", TimeSpan.FromSeconds());
//4.滑动过期时间,3秒后,即三秒钟内被访问,则重新刷新缓存时间为3秒后
memoryCache.Set("key3", "value3", new MemoryCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromSeconds(),
}); Console.WriteLine("-----------暂停2秒");
Thread.Sleep();//暂停2秒
Console.WriteLine($"key1的值:{memoryCache.Get("key1") ?? "key1被清除"}");
Console.WriteLine($"key2的值:{memoryCache.Get("key2") ?? "key2被清除"}");
Console.WriteLine($"key3的值:{memoryCache.Get("key3") ?? "key3被清除"}"); Console.WriteLine("-----------暂停2秒");
Thread.Sleep();//再次暂停2秒
Console.WriteLine($"key1的值:{memoryCache.Get("key1") ?? "key1被清除"}");
Console.WriteLine($"key2的值:{memoryCache.Get("key2") ?? "key2被清除"}");
Console.WriteLine($"key3的值:{memoryCache.Get("key3") ?? "key3被清除"}");
}
}
}

  在栗子中key1,key2都是使用的绝对过期时间,key3使用的相对过期时间,2秒后第一次访问key1、key2、key3都没过期,其中key3的过期时间刷新了,重新设置为3秒后,所以再次暂停2秒后,key1、key2都过期了,key3仍然存在。程序运行结果如下:

2.常用配置

上边我们知道了netcore中缓存的简单用法,下边的栗子介绍netcore中缓存的常用配置,直接看代码

    class Program
{
static void Main(string[] args)
{
//缓存的配置
MemoryCacheOptions cacheOps = new MemoryCacheOptions()
{
//缓存最大为100份
//##注意netcore中的缓存是没有单位的,缓存项和缓存的相对关系
SizeLimit = ,
//缓存满了时,压缩20%(即删除20份优先级低的缓存项)
CompactionPercentage = 0.2,
//两秒钟查找一次过期项
ExpirationScanFrequency = TimeSpan.FromSeconds()
};
MemoryCache myCache = new MemoryCache(cacheOps); //单个缓存项的配置
MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions()
{
//绝对过期时间1
//AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddSeconds(2)),
//绝对过期时间2
//AbsoluteExpirationRelativeToNow=TimeSpan.FromSeconds(3),
//相对过期时间
SlidingExpiration = TimeSpan.FromSeconds(),
//优先级,当缓存压缩时会优先清除优先级低的缓存项
Priority = CacheItemPriority.Low,//Low,Normal,High,NeverRemove
//缓存大小占1份
Size =
};
//注册缓存项被清除时的回调,可以注册多个回调
cacheEntityOps.RegisterPostEvictionCallback((key, value, reason, state) =>
{
Console.WriteLine($"回调函数输出【键:{key},值:{value},被清除的原因:{reason}】");
}); myCache.Set("mykey", "myvalue", cacheEntityOps);
Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}");
Console.WriteLine("------------------暂停3秒");
Thread.Sleep();
Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}"); Console.ReadKey();
}
}
}

  这里需要注意netcore中设置缓存和缓存项大小是没有单位的,缓存被清空的回调函数可以注册多个(System.Runtime.Caching清除缓存的回调只能是一个)。程序执行结果

3.IChangeToken

  上边我们已经简单了解了通过滑动过期时间和绝对过期时间来控制缓存的有效性,但是有时缓存的过期与否和时候没有联系,如我们缓存一个文件的内容,不管缓存多久只要文件没有发生变化缓存都是有效的。在net framework中我们可以通过CacheDependency来控制,在net core中怎么控制呢?net core中我们可以使用IChangeToken接口轻松实现缓存的过期策略。先看一下IChangeToken接口:

    public interface IChangeToken
{
// 是否有变化发生
bool HasChanged { get; } // token是否会调用回调函数,为true时才会有效
bool ActiveChangeCallbacks { get; } // 注册一个回调函数,当有变化时触发回调
IDisposable RegisterChangeCallback(Action<object> callback, object state);
}

看一下IChangeToken实现缓存过期策略的两个例子:

① 监控文件

    class Program
{
static void Main(string[] args)
{
string fileName = Path.Combine(Environment.CurrentDirectory, "someCacheData.xml");
FileInfo fileInfo = new FileInfo(fileName);
MemoryCache myCache = new MemoryCache(new MemoryCacheOptions() { });
MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions();
//PollingFileChangeToken是IChangeToken的实现类,通过轮询监控文件变化
cacheEntityOps.AddExpirationToken(new Microsoft.Extensions.FileProviders.Physical.PollingFileChangeToken(fileInfo));
//缓存失效时,回调函数
cacheEntityOps.RegisterPostEvictionCallback((key, value, reason, state) => { Console.WriteLine($"文件【{key}】改动了"); });
//添加缓存,key为文件名,value为文件内容
myCache.Set(fileInfo.Name, File.ReadAllText(fileName), cacheEntityOps);
Console.WriteLine(myCache.Get(fileInfo.Name));
}
}

  PollingFileChangeToken通过轮询来监控文件有没有发生变化,如果文件中的内容发生改变,缓存就会自动过期。

② 通过代码控制缓存过期

    class Program
{
static void Main(string[] args)
{
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions();
//使用CancellationChangeToken控制缓存过期
CancellationTokenSource tokenSource = new CancellationTokenSource();
cacheEntityOps.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));
//设置缓存
memoryCache.Set("mykey", "myvalue", cacheEntityOps);
Console.WriteLine(memoryCache.Get("mykey") ?? "缓存被清除了");
//通过代码清除缓存
tokenSource.Cancel();
Console.WriteLine(memoryCache.Get("mykey") ?? "缓存被清除了");
}
}

  tokenSource.Cancel方法发送取消信号,这个方法会触发缓存过期,基于此我们可以通过Cancel方法灵活的实现自定义的缓存策略。程序执行结果如下:

2.2 RedisCache

  微软给netcore的缓存提供了Redis和Sqlserver的实现,通过Sqlserver来缓存的场景比较少,这里我们简单看一下官方提供的Redis缓存用法。

  准备工作:我已经在一台Linu虚拟机上部署了Redis服务,虚拟机IP为192.168.70.99,Redis采用默认端口6379,密码是xxxxx。我开发使用的电脑可以连接到虚拟机上的Redis服务器。

  首先添加包

Install-Package Microsoft.Extensions.Caching
Install-Package Microsoft.Extensions.Caching.Redis

  然后我们写一个简单的控制台程序实现一下netcore中的redis缓存实现,代码如下:

        static void Main(string[] args)
{
//获取RedisCache实例
RedisCache redisCache = new RedisCache(new RedisCacheOptions()
{
Configuration = "192.168.70.99:6379,password=xxxxx",
InstanceName = "MyData"
});
//在redis中是以hash表的模式存放的
redisCache.SetString("Name", "jack");
redisCache.SetString("Age", "");
redisCache.SetString("Address", "上海", new DistributedCacheEntryOptions()
{
//SlidingExpiration = TimeSpan.FromSeconds(3)
AbsoluteExpiration = DateTimeOffset.Now.AddDays()
});
//获取缓存
//Console.WriteLine(redisCache.GetString("Name"));
}

  执行完成,缓存数据以Hash表形式存储在redis中,如下:

  这里只是介绍了netcore中redis缓存的简单用法,其实官方提供的Redis缓存扩展中的Api很少,远没有MemoryCache那么多,我们使用netcore中的Redis缓存时,更多要使用Redis自身提供的功能。

netcore中的缓存介绍的更多相关文章

  1. .NET CORE 中的缓存使用

    Net Framewoke的缓存 1.1 System.Web.Caching System.Web.Caching应该是我们最熟悉的缓存类库了,做ASP.NET开发时用到缓存基本都是使用的这个缓存组 ...

  2. Angularjs中的缓存以及缓存清理

    写在最前面:这篇博文是2篇文章组成,详细介绍了Angularjs中的缓存以及缓存清理,文章由上海尚学堂转载过来,欢迎大家阅读和评论.转载请注明出处,谢谢! 一个缓存就是一个组件,它可以透明地储存数据, ...

  3. Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级

    相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...

  4. [原创]关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  5. 03_MyBatis基本查询,mapper文件的定义,测试代码的编写,resultMap配置返回值,sql片段配置,select标签标签中的内容介绍,配置使用二级缓存,使用别名的数据类型,条件查询ma

     1 PersonTestMapper.xml中的内容如下: <?xmlversion="1.0"encoding="UTF-8"?> < ...

  6. 关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  7. c#缓存介绍(转)

    缓存主要是为了提高数据的读取速度.因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能. 本章从缓存 ...

  8. 注释驱动的 Spring cache 缓存介绍

    概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...

  9. [转]注释驱动的 Spring cache 缓存介绍

    原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ 概述 Spring 3.1 引入了激动人心的基于注释(an ...

随机推荐

  1. python中json文件处理涉及的四个函数json.dumps()和json.loads()、json.dump()和json.load()的区分

    一.概念理解 1.json.dumps()和json.loads()是json格式处理函数(可以这么理解,json是字符串) (1)json.dumps()函数是将一个Python数据类型列表进行js ...

  2. windows10安装mysql-8.0.13(zip安装)

    安装环境说明 系统版本:windows10 mysql版本:mysql-8.0.13-winx64.zip 下载地址:http://mirrors.163.com/mysql/Downloads/My ...

  3. docker 发布方式尝试

    docker 发布方式尝试 目前有个小项目, 尝试用docker的方式来发布, 项目只有一个节点, 使用 kubenate 有点小题大做, 所以采用docker-compose来发布. 发布过程 GI ...

  4. 4.26 IO流

  5. Java8-2-Lambda表达式实战-一句话实现Map中按照Value排序

    在上一讲中, 我们着重的讲了表达式的一些基础知识和基本的使用, 今天我们来实战一把, 对Map的Value值排序进行简化. 在以前的思路我们的做法如下: /** * * Map根据value排序; * ...

  6. Web后台快速开发框架

    Web后台快速开发框架 Coldairarrow 目录 目录 第1章    目录    1 第2章    简介    3 第3章    基础准备    4 3.1    开发环境要求    4 3.2 ...

  7. ABP之什么是ABP(ASP.NET Boilerplate)

    1.介绍 ABP是开源的且文档比较齐全的应用程序框架.其实它不仅仅是个框架,考虑其最佳实践,ABP更提供了基于领域驱动设计(DDD)的强大价格模型. ABP支持最新的ASP.NET Core和EF C ...

  8. Linux系统安装jdk教程

    本文仅仅适用于刚刚接触Linux系统的童鞋,毕竟本人也才刚刚玩这个东西,在此记录下以便于以后能查阅及其他童鞋能进行参考,本文为原创随笔,如需转发,请标明出处,谢谢: 此处我采用的是用VMware搭建的 ...

  9. keras03 Aotuencoder 非监督学习 第一个自编码程序

    # keras# Autoencoder 自编码非监督学习# keras的函数Model结构 (非序列化Sequential)# 训练模型# mnist数据集# 聚类 https://www.bili ...

  10. yolov3和darknet opencv版编译安装及基本测试

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 一.准备工作: 安装pkg-config:sudo apt-get install pkg-confi ...