阅读更多

0顶
0踩

Web前端
缓存机制的主要目的是提高应用程序的性能。作为 ASP.NET 开发人员,你可能会意识到 ASP.NET Web 窗体以及 ASP.NET MVC 可以使用 Cache 对象缓存应用程序的数据。这通常被称为服务器端数据缓存,并且常作为框架的内置功能。虽然 ASP.NET Core 中并没有这样的 Cache 对象,但是你可以很容易地实现内存缓存。本文将向你说明如何实现。

在进一步阅读之前,你先创建一个基于 Web 应用程序项目模板的新的 ASP.NET Core 应用程序。

然后按照下面提到的步骤逐一构建和测试由内存缓存提供的各种功能。

1. 内存缓存需要在启动类 Startup 中启用一下

不同于 ASP.NET Web 窗体和 ASP.NET MVC,ASP.NET Core 没有内置的 Cache 对象,可以拿来在控制器里面直接使用。 这里,内存缓存时通过依赖注入来启用的,因此第一步就是在 Startup 类中注册内存缓存的服务。如此,就得打开 Startup 类然后定位到 ConfigureServices() 方法,像下面这样修改 ConfigureServices() 方法:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
        services.AddMemoryCache();
}

为了向你的应用程序加入内存缓存能力,你需要在服务集合上调用 AddMemoryCache() 方法。采用这种办法就可以让一个内存缓存(它是一个 IMemoryCache 对象)的默认实现可以被注入到控制器中去。

2. 内存缓存使用依赖注入来注入缓存对象

然后打开 HomeController 并对其进行修改,如下所示:
public class HomeController : Controller
{
    private IMemoryCache cache;

    public HomeController(IMemoryCache cache)
    {
        this.cache = cache;
    }
    ....
}

如你所见,上述代码声明了一个 ImemoryCache 的私有变量。该变量会被构造器中被赋值。构造器会通过 DI(依赖注入)接收到缓存参数,然后被存储在本地变量总,提供后续使用。

3. 你可以使用 Set() 方法来在缓存中存东西

等你有了这个 IMemoryCache 对象,就可以读取或者向它写入数据了。向缓存写入数据项是相当直接的。
public IActionResult Index()
{
  cache.Set<string>("timestamp", DateTime.Now.ToString());
  return View();
}

上述代码在 Index() 这个 action 中设置了一个缓存项。这是通过使用 IMemoryCache 的 Set<T>() 来完成的。Set() 方法的第一个参数是键名,用来标识该数据项。第二个参数是键的取值。在此例中,我们存储一个字符串的键和一个字符串的值,而你也可以存储其它类型 (原生以及自定义的类型) 的键值对。

4. 你可以使用 Get 方法来从缓存中获取到一个数据项

等你向缓存中添加好了数据,也许会想要在应用程序的其它地方去获取到该数据,可以用 Get() 来做到。如下代码会告诉你如何来做这件事情。
public IActionResult Show()
{
  string timestamp = cache.Get<string>("timestamp");
  return View("Show",timestamp);
}

上述代码从 HomeController 的另外一个action(Show)那里获取到了一个缓存的数据项。Get() 方法会指定数据项的类型以及它的键名。如果该数据项存在的话,就会被返回并且被赋值给 timestamp 这个字符串变量。然后这个 timestamp 的值就会被传递给 Show 视图。

Show 视图只是简单地输出了 timestamp 的值,如下所示:
<h1>TimeStamp : @Model</h1>

<h2>@Html.ActionLink("Go back", "Index", "Home")</h2>


为了对目前为止你所写的代码进行一下测试,请运行应用程序。首先将浏览器导航至 /Home/Index ,这样 timestamp 键就会被赋值。然后导航至 /Home/Show 并查看 timestamp 值是否会输出。下图所示是 Show() 这个 action 运行起来的一个例子。


5. 你可以使用 TryGet() 来检查缓存中是否存在特定的键值

如果你观察前面的示例,会发现每次你导航至 /Home/Index 的时候, 都会有一个新的 timestamp 被赋值给了缓存项。这是因为我们并没有对此进行检查,规定只有在数据项不存在的时候才赋值。许多时候你都会想要这样做的。这里有两种办法可以在 Index() 这个 action 里面来做这样的检查。我们把两种办法都在下面列了出来。
//first way
if (string.IsNullOrEmpty
(cache.Get<string>("timestamp")))
{
  cache.Set<string>("timestamp", DateTime.Now.ToString());
}

//second way
if (!cache.TryGetValue<string>
("timestamp", out string timestamp))
{
    cache.Set<string>("timestamp", DateTime.Now.ToString());
}

第一种办法使用了你早先用过的同一个 Get() 方法,这一次它被拿来跟 if 块一起用。如果 Get() 不能在缓存中找到指定的数据项,IsNullOrEmpty() 就会返回 true。而只有这时候 Set() 才会被调用,一次来添加数据项。

第二种办法更加优雅一点。它使用 TryGet() 方法来获取一个数据项。TryGet() 方法会返回一个布尔值来指明数据项有没有被找到。实际的数据项可以使用一个输出参数拉取出来。如果 TryGet() 返回false,Set() 就会被用来添加数据。

6. 如果不存在的话,可以使用 GetOrCreate() 来添加一项

有时你需要从缓存中检索现有项。如果该项目不存在,则希望添加该项。这两个任务 - 如果它存在获取值,否则创建之 - 可以使用 GetOrCreate() 方法来实现。修改后的 Show() 方法展示了如何实现的。
public IActionResult Show()
{
  string timestamp = cache.GetOrCreate<string>
  ("timestamp", entry => { 
return DateTime.Now.ToString(); });
  return View("Show",timestamp);
}

Show() 动作现在使用 GetOrCreate() 方法。 GetOrCreate() 方法将检查时间戳的键值是否存在。如果是,现有值将被赋值给局部变量。否则,将根据第二个参数中指定的逻辑创建一个新条目并将其添加到缓存中。

为了测试此代码,请直接运行 /Home/Show,不需要跳转到 /Home/Index。你仍然会看到输出的时间戳值,因为在该值不存在的情况下,GetOrCreate() 现在是添加了它。

7. 你可以在一个缓存的数据项上面设置绝对和滚动的过期时间

在前述示例中,一个缓存项只要被添加到缓存就会一直存储,除非它被明确地使用 Remove() 从缓存中移除。你也可以在一个缓存项上面设置一个绝对和滚动的过期时间。一个绝对的过期设置意味着该缓存项会在严格指定的日期和时间点被移除,而滚动过期设置则意味着它在给定的一段时间量处于空闲状态(也就是没人去访问)之后被移除。

为了能在一个缓存项上面设置这两种过期策略,你要用到 MemoryCacheEntryOptions 对象。如下代码向你展示了如何去使用。
MemoryCacheEntryOptions options = 
new MemoryCacheEntryOptions();
options.AbsoluteExpiration = 
DateTime.Now.AddMinutes(1);
options.SlidingExpiration = 
TimeSpan.FromMinutes(1);
cache.Set<string>("timestamp", 
DateTime.Now.ToString(), options);

上述代码来自于修改过的 Index() action,它创建了一个 MemoryCacheEntryOptions 的对象,然后将它的 AbsoluteExpiration 属性设置为从此刻到一分钟之后的一个 DateTime 值,它还将 SlidingExpiration 属性设置为一分钟。这些值都指定了该缓存项会在一分钟之后从缓存移除,不管其是否会被访问。此外,如果该缓存项如初持续空闲了有一分钟,它也会被从缓存中移除。

等你将 AbsoluteExpiration 和 SlidingExpiration 的值设置后, Set() 方法就可以被用来将一个数据项添加到缓存。这一次 MemoryCacheEntryOptions 对象会被作为第三个参数传递给 Set() 方法。

8. 当缓存项会被移除时,你可以连接回调

有时你会想要在缓存项从缓存中被移除时收到通知。可能会有多种原因需要从缓存中移除数据项。例如,因为明确地执行了 Remove() 方法而移除了一个缓存项, 也有可能是因为它的 AbsoluteExpiration 和 SlidingExpiration 值已经到期而被移除,诸如此类的原因。

为了能知道项目是何时从缓存移除的,你需要编写一个缓存函数。如下代码向你展示了如何去做这件事情:
MemoryCacheEntryOptions options = 
new MemoryCacheEntryOptions();
options.AbsoluteExpiration = 
DateTime.Now.AddMinutes(1);
options.SlidingExpiration = 
TimeSpan.FromMinutes(1);
options.RegisterPostEvictionCallback
(MyCallback, this);
cache.Set<string>("timestamp", 
DateTime.Now.ToString(), options);

上述代码同之前使用 MemoryCacheEntryOptions 来配置 AbsoluteExpiration 和 SlidingExpiration 的代码相当类似。更加重要的是它也调用了 RegisterPostEvictionCallback() 方法来绑定刚刚讨论过的回调函数。在这里回调函数被命名为 MyCallback。第二个参数是一个你会想要传递给回调函数的状态对象。这里我们传入了 HomeController 的实例 (用 this 将当前的 HomeController 对象“点”出来) 作为状态对象。

前面提到的MyCallback函数,其代码如下所示:
private static void MyCallback(object key, object value,
EvictionReason reason, object state)
{
    var message = $"Cache entry was removed : {reason}";
    ((HomeController)state).
cache.Set("callbackMessage", message);
}

请仔细观察这段代码。 MyCallback() 是 HomeController 类里面的一个私有静态函数,它有四个参数。前面两个参数表示刚刚删除的缓存项的键和值,第三个参数表示的是该数据项被删除的原因。EvictionReason 是一个枚举类型,它维护者各种可能的删除原因,如过期,删除以及替换。
在回调函数的内部,我们会基于删除的原因构造一个字符串消息。我们想要将此消息设置成另外一个缓存项。这样做的话就需要访问 HomeController 的缓存对象,此时状态参数就可以排上用场了。使用状态对象,你可以对 HomeController 的缓存对象进行控制,并使用 Set() 增加一个 callbackMessage 缓存项。
你可以通过 Show() 这个 action 来访问到 callbackMessage,如下所示:
public IActionResult Show()
{
  string timestamp = cache.Get<string>("timestamp");
  ViewData["callbackMessage"] = 
    cache.Get<string>("callbackMessage");
  return View("Show",timestamp);
}

最后就可以在 Show 视图中显示出来了:
<h1>TimeStamp : @Model</h1>

<h3>@ViewData["callbackMessage"]</h3>

<h2>@Html.ActionLink("Go back", "Index", "Home")</h2>

为了测试回调,我们需要运行应用程序并跳转到 /Home/Index。然后跳转到 /Home/Show,并不停地刷新浏览器。在某些时间点,由于其 AbsoluteExpiration 设置之后,时间戳项目将会过期。你会看到这样的 callbackMessage:

9. 你可以设置缓存项的优先级

正如你可以设置缓存项的到期策略一样,你还可以为缓存项赋予优先级。如果服务器内存紧缺的话,就会基于此优先级对缓存项进行清理以回收内存。 想要设置优先级的话,就要再一次用到 MemoryCacheEntryOptions。
MemoryCacheEntryOptions options = 
new MemoryCacheEntryOptions();
options.Priority = CacheItemPriority.Normal;
cache.Set<string>("timestamp", 
DateTime.Now.ToString(), options);

MemoryCacheEntryOptions 的 Priority 属性让你可以使用 CacheItemPriority 枚举来设置缓存项的优先级取值。可选的值有 Low,Normal,High 以及 NeverRemove。

10. 你可以设置多个缓存项之间的依赖关系

你还可以对一组缓存项目之间的依赖关系进行设置,例如在删除一个缓存项时,所有依赖的项也会被删除。 要是你想要了解它是如何工作的,可以像下面这样对 Index()这个 action 做一下修改:
public IActionResult Index()
{
    var cts = new CancellationTokenSource();
    cache.Set("cts", cts);

    MemoryCacheEntryOptions options = 
new MemoryCacheEntryOptions();
    options.AddExpirationToken(
new CancellationChangeToken(cts.Token));
    options.RegisterPostEvictionCallback
(MyCallback, this);
    cache.Set<string>("timestamp", 
DateTime.Now.ToString(), options);

    cache.Set<string>("key1", "Hello World!", 
new CancellationChangeToken(cts.Token));
    cache.Set<string>("key2", "Hello Universe!", 
new CancellationChangeToken(cts.Token));

    return View();
}

代码首先创建了一个 CancellationTokenSource 对象,该对象被存储为一个独立的缓存项 cts。然后像之前那样创建出 MemoryCacheEntryOptions 对象。这时候调用 MemoryCacheEntryOptions 的  AddExpirationToken() 方法来指定过期令牌。我们不会在这里探讨 CancellationChangeToken 的细节。可以这样理解,过期令牌能让你有权利让一个缓存项过期。如果令牌处于活动状态的话,则缓存项就会在缓存中维持,而如果令牌被取消掉了,则该缓存项就将从缓存中删除掉。一旦缓存项从缓存中删除掉了,MyCallback 就像之前一样被调用。之后代码又创建了两个缓存项—— key1 和 key2。在添加这两个缓存项时,Set() 的第三个参数将基于之前所创建的 cts 对象传递一个 CancellationChangeToken。

这样做就意味着这里我们有了三个键 - timestamp 是主键,而 key1 和 key2 则依赖于 timestamp。当 timestamp 被删除时,key1 和 key2 也应该被删除掉。要删除 timestamp,你需要在代码中的某个地方取消其令牌。我们可以单独的一个 action(Remove())中进行这样的操作。
public IActionResult Remove()
{
    CancellationTokenSource cts = 
cache.Get<CancellationTokenSource>("cts");
    cts.Cancel();
    return RedirectToAction("Show");
}

这里我们先获取到之前存储的 CancellationTokenSource 对象,并调用它的 Cancel() 方法。这样做会把 timestamp,key1 以及 key2 都删除掉。 你可以通过在 Show() 这个 action 中获取一下所有这三个键来确认它们是否已经被删除掉了。

为了测试这个例子,运行应用程序并导航至 /Home/Index。然后再导航至 /Home/Show,并检查所有这三个键值是否按预期显示了出来。然后导航至 /Home/ Remove,浏览器将被重定向回 /Home/Show。由于 Remove() 取消了令牌,所有的键都已经被删除调了,而现在 Show 视图会将删除的原因(TokenExpired)显示出来,如下所示:

到目前为止就是这些了!笔耕不辍!

英文原文:10 Things To Know About In-Memory Caching In ASP.NET Core
参与翻译: leoxu, Tocy, 无若
  • 大小: 58.9 KB
  • 大小: 45.2 KB
  • 大小: 42.4 KB
  • 大小: 43.7 KB
来自: oschina
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • ASP.NET缓存介绍

    缓存是在内存存储数据的一项技术,也是ASP.NET中提供的重要特性之一。例如你可以在复杂查询的时候缓存数据,这样后来的请求就不需要从数据库中取数据,而是直接从缓存中获取。通过使用缓存可以提高应用程序的性能

  • ASP.NET2.0缓存(Cache)技术深入理解

    ASP.NET2.0提供了一些新的用于提升程序性能的技术特性,其中,缓存技术是非常重要的一个特性,它提供了一种非常好的本地数据缓存机制,从而有效的提高数据访问的性能。 数据缓存(DataCaching)就是将数据暂存于内存...

  • ASP.NET页面缓存常见的4种方式

    本文为大家分享了4种常见的ASP.NET页面缓存方式,供大家参考,具体内容如下 1、分布式缓存Memcached,教程下载 2、内存缓存,此占用服务器资源 #region 内存缓存 public class MemoryCache { #region 写 /// ...

  • 浅说ASP.NET 缓存

    因此,整个页面必须是动态生成且不能缓存的,但其中有一小块用于放置过去一周的趋势图或成交量,它存储的是历史数据,这些数据早已是固定的事实,或者需要很长一段时间后才重新统计变动,将这部分缓存下来有很高的...

  • asp.net中C#实现手动回收内存的方法

    主要介绍了asp.net中C#实现手动回收内存的方法,包括System.GC.Collect方法的使用及缓存技术的分析,具有一定的实用价值,需要的朋友可以参考下

  • ASP.NET缓存的方法和最佳实践

    这里再次强调,内存现在非常便宜,因此,如果您能通过将输出缓存 30 秒,而不是花上一整天甚至一周的时间尝试优化代码或数据库就可以获得所需的性能,您肯定会选择缓存解决方案(假设可以接受 30 秒的旧数据)。缓存...

  • ASP.NET Core 中使用缓存

    ASP.NET Core 中使用缓存

  • asp.net core 服务器端 内存缓存 的使用

    2.通过 SlidingExpiration 属性 设置 滑动过期时间 -- 值的是 设定了时间,如果在设定的时间段没有一次访问,这个时间到期 就会清除 缓存,如果在 这个时间没有 到期 时 一直访问 就会 一直自动续时。当某一个时刻...

  • 充分利用ASP.NET的三种缓存提高站点性能的注意方法

    ASP.NET提供三种主要形式的缓存:页面级输出缓存、用户控件级输出缓存(或称为片段缓存)和缓存API。 尽早缓存;经常缓存 您应该在应用程序的每一层都实现缓存。向数据层、业务逻辑层、UI或输出层添加缓存支持。...

  • ASP.NET Core 内存缓存使用方法

    ASP.NET Core 支持多个不同的缓存。 最简单的缓存基于 IMemoryCache。 IMemoryCache 表示存储在 Web 服务器内存中的缓存。IMemoryCache 更适用于 ASP.NET Core 依赖关系注入。缓存可以存储任何对象,缓存项均存储为...

  • Asp.NET Core 缓存问题的总结

    一、HTTP响应缓存报文头 cache-control 二、内存缓存(In-memory Cache) 三、分布式缓存 四、缓存穿透问题 五、缓存雪崩问题

  • asp.net 页面输出缓存

    最简单的缓存机制,把整个Aspx页面保存在服务器端内存中,用户请求页面时,直接从服务器端内存中提取数数据,不在经历页面的生命周期。

  • 《解剖PetShop》之四:PetShop之ASP.NET缓存

    四 PetShop之ASP.NET缓存  如果对微型计算机硬件系统有足够的了解,那么我们对于Cache这个名词一定是耳熟能详的。在CPU以及主板的芯片中,都引入了这种名为高速缓冲存储器(Cache)的技术。因为Cache的存取速度比...

  • Asp.net 数据缓存

    Asp.net 数据缓存asp.net中缓存的使用介绍介绍: 缓存是一种在计算机中广泛用来提高性能的技术,它将访问频率高或者构造成本高的数据保留在内存中。在Web应用程序的上下文中,缓存用于在HTTP请求时保留页或者数据,...

  • 对asp.net缓存 的深入了解

    ——————————————————————————– 缓存是一种用空间换取时间的技术,通俗点也就是说把你得到的数据存放在内存中一段时间,在这短时间内服务器不去读取数据库、或是真实的数据源,而是读取你...

  • ASP.NET Core 性能优化-缓存

    ASP.NET Core 性能优化 缓存 ASP.NET Core 客户端缓存 ASP.NET Core 服务端缓存 服务器端响应缓存很鸡肋 内存缓存(In-memory cache) 缓存的过期时间策略 过期时间的两种策略 绝对过期时间 滑动过期时间 两种过期...

  • ASP.NET2.0中改进的缓存功能

    摘要:本文中,StephenWalther将重点介绍ASP.NET2.0中新增的缓存功能,以及如何使用这些新功能改进ASP.NET应用程序的性能和可扩展性。(本文包含一些指向英文站点的链接。)本页内容更轻松的数据缓存使用...

  • Asp.Net缓存——客户端缓存

    Asp.net缓存 将常用的数据保存在内存中对asp的开发人员来说并不陌生,Session对象和Application对象提供键值对来缓存数据,Session对象保存和单个用户有关的数据,Application对象可保留和应用程序有关的数据,每个...

  • .NET ASP.NET 中的缓存Cache

    一.为什么要引入缓存Cache? 我们知道,造成高并发的原因是大量读写的问题,一般的对于一个系统,读总是比写多,如我们总是逛淘宝,京东,天猫,唯品会等,但我们...很好,我们知道缓存主要解决读的问题,那么,我...

  • 前18大旋转修整器企业占据全球87%的市场份额.docx

    前18大旋转修整器企业占据全球87%的市场份额

Global site tag (gtag.js) - Google Analytics