这篇文章讲解分布式缓存,即 Distributed caching in ASP.NET Core

Distributed caching in ASP.NET Core

分布式缓存是可以在多个应用服务上共享的缓存,比较经典的用法是作为多个应用服务器的一个可到达的外部服务。分布式缓存可以提高 ASP.NET Core应用的性能和扩展性(performance and scalability), 特别是当应用是部署在云服务器或者服务器集群上时。

分布式缓存比其他缓存存储在独立服务器上的场景有几个优点。

当缓存数据是分布式的:

  • 跨多个服务器的请求时,数据是一致的
  • 比服务器重启和应用部署存在的时间长
  • 不使用本地内存

不同分布式缓存的实现,它们的配置不同。这篇文章会讲解怎样配置 SQL Server分布式缓存 和 Redis分布式缓存 。第三方实现也是可用的,例如,NCache. 不管选择那一种实现,应用和缓存都是使用 IDistributedCache接口交互。

一.Prerequisites(先决条件)

1. 要使用SQL Server分布式缓存,需要引入 Microsoft.AspNetCore.App metapackage 或者 添加 Microsoft.Extensions.Caching.SqlServer 包的引用

2. 要使用Redis 分布式缓存,需要引用  Microsoft.AspNetCore.App metapackage 并且添加  Microsoft.Extensions.Caching.StackExchangeRedis 包的引用。因为Redis包没有包含在 Microsoft.AspNetCore.App 中,所以必须分开引用Redis包。

二. IDistributedCache interface

IDistributedCache接口提供下列方法来操作分布式缓存中的数据项:

  • GetGetAsync  :接受string类型的key, 如果在缓存中找到了,缓存数据会以byte[]数组的形式输出
  • SetSetAsync :往缓存中添加缓存数据
  • RefreshRefreshAsync : 根据key值,刷新缓存中的数据项,重置它的过期时间
  • RemoveRemoveAsync : 删除缓存的数据项

三. Establish distributed caching services (建立分布式服务)

在Startup.ConfigureServices中注册一个IDistributedCache的实现。Framework提供的实现在这个主题会做一些描述,包括:

  • Distributed Memory Cache(分布式内存缓存)
  • Distributed SQL Server cache(分布式SQL Server缓存)
  • Distributed Redis cache(分布式Redis缓存)

1. Distributed Memory Cache

Distributed Memory Cache 是存储在内存中的 , 它不是一个现实(actual)中的分布式缓存。缓存数据是存储在应用运行的服务器上的。

分布式内存缓存是一个有用的实现:

  • 在开发和测试场景

  • 当生产环境是在一个单独的服务器,并且内存消耗不是一个问题时。实现分布式内存缓存来简化数据存储。它允许在将来实现一个真正的分布式缓存解决方案如果多个结点或者容错成为可能 。(Implementing the Distributed Memory Cache abstracts cached data storage. It allows for implementing a true distributed caching solution in the future if multiple nodes or fault tolerance become necessary.)

这个示例中,应用是运行在开发环境,在 Startup.ConfigureServices中 ,使用 Distributed Memory Cache :

services.AddDistributedMemoryCache();

2. Distributed SQL Server Cache

分布式SQL Server 缓存实现允许分布式缓存使用SQL Server数据库作为一个存储备份。要在SQL Server实例中创建一个SQL Server缓存项(cached item),你应该用sql-cache工具。这个工具用你提供的name和schema创建一个table.

在SQL Server中通过运行sql-cache create命令创建一个table. 提供SQL Server实例(Data Source),数据库(Initial Catalog),schema(例如, dbo),和表名(例如,TestCache):

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

成功后,显示:

Table and index were created successfully.

通过sql-cache工具创建的表(table)有下列的schema:

注意:应用在操作缓存值时,应该使用IDistributedCache,而不是一个SqlServerCache.即使用接口的方式

这个示例应用实现了SqlServerCache,在非开发环境,在Startup.ConfigureServices:

services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});

3.  Distributed Redis Cache

Redis是一个开源的in-memory 数据存储,它经常用作一个分布式缓存。你可以在本地使用Redis,并且你可以配置Azure Redis Cache为一个Azure-hosted ASP.NET Core应用。

一个应用配置缓存实现,使用一个RedisCache实例在一个非开发环境,在Startup.ConfigureServices:

services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});

使用本地机器上的Redis时,需要下载Redis,并且运行redis-server 。

好了,上面的1,2,3是讲解不同缓存在 Startup.ConfigureServices 中的配置,使添加到项目中。下面讲下如何使用

四.Use the distributed cache

要使用IDistributedCache接口,可以从应用中的任意构造函数中,请求一个IDistributedCache实例.这个实例通过依赖注入提供。

当应用启动时,IDistributedCache被注入到Startup.Configure中。使用IApplicationLifetime使当前时间被缓存。

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
IApplicationLifetime lifetime, IDistributedCache cache)
{
lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString(); //当前时间
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds());
cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

在这个示例应用中,会把 IDistributedCache注入到IndexModel中被Index page使用。

代码如下:

public class IndexModel : PageModel
{
private readonly IDistributedCache _cache; public IndexModel(IDistributedCache cache)
{
_cache = cache;
} public string CachedTimeUTC { get; set; } public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC"); if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
} public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds());
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options); return RedirectToPage();
}
}

注意:对于IDistributedCache实例,没有必要使用单例(Singleton)或者Scoped lifetime。(至少对于内置的实现没有必要)

五.Recommendations

当考虑使用IDistributedCache的哪一种实现对于你的应用最合适时,可以考虑下:

  • Existing infrastructure 已存在的基础设施

  • Performance requirements 表现(性能)要求

  • Cost 花销

  • Team experience 团队经验

缓存解决方案通常依赖in-memory storage(内存存储)来提供对缓存数据的快速检索。但是内存是一个有限的资源,并且很难扩展(costly to expand;costly,昂贵的)。仅将常用数据存储在缓存中。

通常来说,一个Redis cache比一个SQL Server cache 能提供更高的吞吐量(throughput:生产量,生产能力,吞吐量),并且更低的潜伏因素(latency:潜伏,潜伏因素). 然而,大家通常使用 benchmarking来判断the performance characteristics of caching strategies(缓存策略的表现性能)。

当SQL Server被用作一个分布式缓存备份存储。使用同一个数据库来缓存和普通数据的存储,和检索,会消极的影响两者的表现。我们建议为分布式缓存备份存储使用一个专用的SQL Server实例。

参考资料:

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.2

asp.net core 系列之Response caching 之 Distributed caching(3)的更多相关文章

  1. asp.net core 系列之Response caching(1)

    这篇文章简单的讲解了response caching: 讲解了cache-control,及对其中的头和值的作用,及设置来控制response caching; 简单的罗列了其他的缓存技术:In-me ...

  2. Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)

    Ajax跨域问题及解决方案   目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...

  3. asp.net core系列 38 WebAPI 返回类型与响应格式--必备

    一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...

  4. asp.net core 系列 16 Web主机 IWebHostBuilder

    一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...

  5. asp.net core 系列 14 错误处理

    一.概述 本文介绍处理 ASP.NET Core 应用中常见错误的一些方法.主要是关于:开发环境异常页:非开发环境配置自定义异常处理页:配置状态代码页(没有正文响应,http状态400~599的). ...

  6. asp.net core 系列 8 Razor框架路由(下)

    三.页面路由操作约定 接着上篇讲asp.net core 系列 7 Razor框架路由.在上篇继续第三节 "页面路由操作约定" 的最后一小节 AddPageRoute . 3.3. ...

  7. 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)

    黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...

  8. 【asp.net core 系列】10 实战之ActionFilter

    0.前言 在上一篇中,我们提到了如何创建一个UnitOfWork并通过ActionFilter设置启用.这一篇我们将简单介绍一下ActionFilter以及如何利用ActionFilter,顺便补齐一 ...

  9. 1.1专题介绍「深入浅出ASP.NET Core系列」

    大家好,我是IT人张飞洪,专注于.NET平台十年有余. 工作之余喜欢阅读和写作,学习的内容包括数据结构/算法.网络技术.Linux系统原理.数据库技术原理,设计模式.前沿架构.微服务.容器技术等等…… ...

随机推荐

  1. struts2 no extension(excludePattern)

    采用struts2 小伙伴非常希望更改或删除action扩展,本文将帮助你实现 struts2-core-2.3.16.jar , 下载链接: http://repo1.maven.org/maven ...

  2. zabbix 设备(自己的实践)

    1. 下载源代码包 wget http://sourceforge.net/projects/zabbix/files/ 2.  解压 tar -zxvf zabbix-2.2.3.tar.gz 3. ...

  3. SpringBoot、Groovy

    Java——搭建自己的RESTful API服务器(SpringBoot.Groovy)   这又是一篇JavaWeb相关的博客,内容涉及: SpringBoot:微框架,提供快速构建服务的功能 Sp ...

  4. 微信公众平台中临时二维码的scene_id为32位非0整型

    原文:微信公众平台中临时二维码的scene_id为32位非0整型                                        微信公众平台中临时二维码的scene_id为32位非0整 ...

  5. VS2005 编译 Qt4.8.2库,并修正源码中的错误

    从昨天开始利用VS2005对Qt4.8.2库进行编译,在编译到某个文件时,总是报错,提示VS的cl.exe和nmake.exe返回致命错误.错误罗列如下: DefaultLocalizationStr ...

  6. 简明Python3教程 11.数据结构

    简介 数据结构基本上就是 – 可以将一些数据结合到一起的结构,换言之用于存储一组相关的数据. python拥有4种内建数据结构 – 列表,元组(tuple),字典和集合. 我们将看到如何它们,它们又是 ...

  7. MySQL SYS CPU高的案例分析(一)

    原文:MySQL SYS CPU高的案例分析(一) [现象] 最近关注MySQL CPU告警的问题时,发现有一种场景,有一些服务器最近都较频繁的出现CPU告警,其中的现象是 SYS CPU占比较高. ...

  8. 构建自己的PHP框架(MVC)

    完整项目地址:https://github.com/Evai/Aier 规划文件夹 新建 MFFC/app 文件夹,在 app 中创建 controllers.models.views 三个文件夹,开 ...

  9. EJB什么,它真的有这么神奇??

    1. 我们不禁要问,什么是"服务集群"?什么是"企业发展"? 现在说EJB 至"服务集群"和"企业发展",然后,说什么是 ...

  10. go与java互用的AES实现

    终于实现了go与java互用的AES算法实现.基于go可以编译windows与linux下的命令行工具,十分方便. Java源码 import java.security.GeneralSecurit ...