欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET Core应用中使用分布式缓存及内存缓存

程序员文章站 2022-05-10 20:48:57
.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中。对于分布式缓存,.NET Core提供了针对Redis和SQL Server的原生支持。除了这个独立的缓存系统之外,ASP.NET Core还借... ......

.net core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中。对于分布式缓存,.net core提供了针对redis和sql server的原生支持。除了这个独立的缓存系统之外,asp.net core还借助一个中间件实现了“响应缓存”,它会按照http缓存规范对整个响应实施缓存。asp.net core 支持多种不同的缓存。

常见缓存响应的四种方式

1、内存缓存

  顾名思义,缓存在内存中,生命周期默认伴随应用程序

2、响应缓存

  响应缓存可减少客户端或代理到 web 服务器发出的请求数。 响应缓存还减少了工作的 web 服务器执行以生成响应。 响应缓存控制标头,指定要如何客户端、 代理和响应缓存中间件。

3、响应缓存中间件

  microsoft.aspnetcore.responsecaching 包中的responsecaching

4、分布式缓存

  比较常用的是基于redis和数据库的分布式缓存。

在这里我们重点说说内存缓存和分布式缓存。

如果你看到这段文字,说明您正使用rss阅读或转自《一棵树-博客园》,原文地址:https://www.cnblogs.com/atree/p/netcore-distributed-cache.html 

将数据缓存在内存中-内存缓存

与针对数据库和远程服务调用这种io操作来说,应用针对内存的访问性能将提供不止一个数量级的提升,所以将数据直接缓存在应用进程的内容中自然具有最佳的性能优势。与基于内存的缓存相关的应用编程接口定义在nuget包“microsoft.extensions.caching.memory”中,具体的缓存实现在一个名为memorycache的服务对象中,后者是我们对所有实现了imemorycache接口的所有类型以及对应对象的统称。由于是将缓存对象直接置于内存之中,中间并不涉及持久化存储的问题,自然也就无需考虑针对缓存对象的序列化问题,所以这种内存模式支持任意类型的缓存对象。

针对缓存的操作不外乎对缓存数据的存与取,这两个基本的操作都由上面介绍的这个memorycache对象来完成。如果我们在一个asp.net core应用对memorycache服务在启动时做了注册,我们就可以在任何地方获取该服务对象设置和获取缓存数据,所以针对缓存的编程是非常简单的。不想看这些,直接看案例。

static void main (string[] args) 
{ memorycache memorycache = new memorycache(new memorycacheoptions()); memorycache.set("name", "tom"); var value = memorycache.get("name"); console.writeline(value); console.readkey(); }

 设置过期时间:

static void main (string[] args) 
{ memorycache memorycache = new memorycache (new memorycacheoptions ()); memorycache.set ("name", "jack", new memorycacheentryoptions () { absoluteexpiration = datetimeoffset.now.addseconds (5) //设置为5秒后过期 }); while (true) { system.threading.thread.sleep (1000); string value; if (!memorycache.trygetvalue ("name", out value)) { value = "已过期"; } console.writeline (value); } }

基于内存的缓存具有最高的性能,但是由于它实际上是将缓存数据存在承载asp.net core应用的web服务上,对于部署在集群式服务器中的应用会出现缓存数据不一致的情况。对于这种部署场景,我们需要将数据缓存在某一个独立的存储中心,以便让所有的web服务器共享同一份缓存数据,我们将这种缓存形式称为“分布式缓存”。asp.net core为分布式缓存提供了两种原生的存储形式,一种是基于nosql的redis数据库,另一种则是微软自家关系型数据库sql server。

基于redis的分布式缓存

redis数目前较为流行nosql数据库,很多的编程平台都将它作为分布式缓存的首选,接下来我们来演示如何在一个asp.net core应用中如何采用基于redis的分布式缓存。考虑到一些人可能还没有体验过redis,所以我们先来简单介绍一下如何安装redis。redis最简单的安装方式就是采用chocolatey(https://chocolatey.org/) 命令行,后者是windows平台下一款优秀的软件包管理工具(类似于npm)。

采用powershell (要求版本在v3以上)命令行

iwr https://chocolatey.org/install.ps1 -usebasicparsing | iex

或者普通cmd.exe命令行:

@powershell -noprofile -executionpolicy bypass -command "iex ((new-object system.net.webclient).downloadstring('https://chocolatey.org/install.ps1'))" && set "path=%path%;%allusersprofile%\chocolatey\bin"

来安装chocolatey。在确保chocolatey 被本地正常安装情况下,我们可以执行执行如下的命令安装或者升级64位的redis。

c:\>choco install redis-64
c:\>choco upgrade redis-64

redis服务器的启动也很简单,我们只需要以命令行的形式执行redis-server命令即可。如果在执行该命名之后看到如下图所示的输出,则表示本地的redis服务器被正常启动,输出的结果会指定服务器采用的网络监听端口。为了方便管理,可以下载安装:客户端工具:redisdesktopmanager。

.NET Core应用中使用分布式缓存及内存缓存

针对redis的分布式缓存实现在nuget包“microsoft.extensions.caching.redis”之中,所以我们需要确保该nuget包被正常安装。不论采用redis、sql server还是其他的分布式存储方式,针对分布式缓存的操作都实现在distributedcache这个服务对象向,该服务对应的接口为idistributedcache。

idistributedcache接口包含同步和异步方法。 接口允许在分布式缓存实现中添加、检索和删除项。 idistributedcache接口包含以下方法:

get、 getasync

采用字符串键并以byte[]形式检索缓存项(如果在缓存中找到)。

set、setasync

使用字符串键向缓存添加项byte[]形式)。

refresh、refreshasync

根据键刷新缓存中的项,并重置其可调过期超时值(如果有)。

remove、removeasync

根据键删除缓存项。

在项目启动setup.cs中注册:redis服务

public void configureservices (iservicecollection services) 
{ //将redis分布式缓存服务添加到服务中 services.adddistributedrediscache (options => { //用于连接redis的配置 configuration.getconnectionstring("redisconnectionstring")读取配置信息的串 options.configuration = "localhost"; // configuration.getconnectionstring("redisconnectionstring"); //redis实例名redisdistributedcache options.instancename = "redisdistributedcache"; }); services.addmvc (); }

实例对象,构造注入

private distributedcache _cache;

/// <summary>
///   构造注入
/// </summary>
/// <param name="cache"></param>
public valuescontroller (idistributedcache cache) {
    _cache = new distributedcache (cache);
}

调用distributedcache 类中的方法

[httpget ("{id}")]
public string get (int id) {
    //添加
    bool booladd = _cache.add ("id", "sssss");
    //验证
    bool boolexists = _cache.exists ("id");
    //获取
    object obj = _cache.get ("id");
    //删除
    bool boolremove = _cache.remove ("id");
    //修改
    bool boolmodify = _cache.modify ("id", "ssssssss");

    return obj.tostring ();
}

基于sql server的分布式缓存

除了使用redis这种主流的nosql数据库来支持分布式缓存,微软在设计分布式缓存时也没有忘记自家的关系型数据库采用sql server。针对sql server的分布式缓存实现在“microsoft.extensions.caching.sqlserver”这个nuget包中,我们先得确保该nuget包被正常装到演示的应用中。

所谓的针对sql server的分布式缓存,实际上就是将标识缓存数据的字节数组存放在sql server数据库中某个具有固定结构的数据表中,因为我们得先来创建这么一个缓存表,该表可以借助一个名为sql-cache 的工具来创建。在执行sql-cache 工具创建缓存表之前,我们需要在project.json文件中按照如下的形式为这个工具添加相应的nuget包“microsoft.extensions.caching.sqlconfig.tools”。

在 sqlserver 数据库引擎中创建一个数据库,命名为:testdb,打开项目根目录,执行创建缓存数据表的操作,执行命令后如果输出信息:table and index were created successfully. 表示缓存表创建成功.

dotnet sql-cache create "server=.\sqlexpress;user=sa;password=123456;database=testdb" dbo aspnetcorecache

在 startup.cs 中注册分布式缓存

public void configureservices (iservicecollection services) {
    services.adddistributedsqlservercache (options => {
        options.systemclock = new bll.localsystemclock ();
        options.connectionstring = this.configuration["connectionstring"];
        options.schemaname = "dbo";
        options.tablename = "aspnetcorecache";
        options.defaultslidingexpiration = timespan.fromminutes (1);
        options.expireditemsdeletioninterval = timespan.fromminutes (5);
    });
    ...
}

在控制器中使用分布式缓存

[route ("api/home")]
[apicontroller]
public class homecontroller : controller {
    private idistributedcache cache;
    public homecontroller (idistributedcache cache) {
        this.cache = cache;
    }

    [httpget ("index")]
    public async task<actionresult<string>> settime () {
        var currenttime = datetime.now.tostring ();
        await this.cache.setstringasync ("currenttime", currenttime);
        return currenttime;
    }

    [httpget ("gettime")]
    public async task<actionresult<string>> gettime () {
        var currenttime = await this.cache.getstringasync ("currenttime");
        return currenttime;
    }
}

就这样,用起来挺方便的。