这篇文章讲解分布式缓存,即 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. CentOS 7 部署 ASP.NET Core 应用程序

    原文:CentOS 7 部署 ASP.NET Core 应用程序 看了几篇大牛写的关于 Linux 部署 ASP.NET Core 程序的文章,今天来实战演练一下.2017年最后一个工作日,提前预祝大 ...

  2. Linux经常使用的命令(两) - cd

    Linux cd 命令能够说是Linux中最主要的命令语句,其它的命令语句要进行操作,都是建立在使用 cd 命令上的.所以,学习Linux 经常使用命令.首先就要学好 cd 命令的用法技巧. 1. 命 ...

  3. Java中,对多线程访问同一变量(并发访问)的认识

    在Java中,如果启动多个线程对同一个对象或者变量时候,在没有安全保护前提下有可能会抛出并异常 java.util.ConcurrentModificationException 当方法检测到对象的并 ...

  4. WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)

    原文 WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口) WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验.如果希望做不同线程 ...

  5. uwp - 获取当前屏幕宽高/应用宽高

    原文:uwp - 获取当前屏幕宽高/应用宽高 public static Size GetScreen() { var applicationView = ApplicationView.GetFor ...

  6. silverlight,WPF动画终极攻略之番外 3D切换导航篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之番外 3D切换导航篇(Blend 4开发) 这篇介绍的是3D导航,点击图标,页面360°翻转的效果!有什么不足的欢迎大家指出来. 1.新建一个user ...

  7. 零元学Expression Design 4 - Chapter 2 熟悉Design并且快速设计出Silverlight网页

    原文:零元学Expression Design 4 - Chapter 2 熟悉Design并且快速设计出Silverlight网页 本章将用带大家熟悉Design 4并制作简易的网页版面,也会让你了 ...

  8. 在Eclipse安装ADT

    Eclipse 3.4 (Ganymede) 启动 Eclipse,然后选择 Help > Software Updates….在出现的对话框中.单击 Available Software 选项 ...

  9. Kubernetes使用集群联邦实现多集群管理

    Kubernetes在1.3版本之后,增加了“集群联邦”Federation的功能.这个功能使企业能够快速有效的.低成本的跨区跨域.甚至在不同的云平台上运行集群.这个功能可以按照地理位置创建一个复制机 ...

  10. WPF依赖属性对内存的使用方式

    WPF允许对象在创建时候并不包含存储数据的空间,只保留在用到时获取数据默认值,借用其他对象数据或者实时分配空间的能力