在asp.netcore应用中使用imemorycache缓存(代码片段)

JimCarter JimCarter     2023-03-09     191

关键词:

1. 简介

Caching通过减少生成内容所需的工作,显著提高应用的性能和可伸缩性。 Caching适用于不经常更改且生成成本高的数据。

ASP.NET Core支持多个不同的缓存。 最简单的缓存基于 IMemoryCacheIMemoryCache 属于内存缓存,存在于应用内部。如果使用内存缓存,后续请求需要都请求到这一个应用上,才能有效利用这个缓存,否则会有缓存一致性的问题。如果没办法保证这一点,则可以使用分布式缓存来解决。对于某些应用,分布式缓存可以支持比内存中缓存更高的横向扩展。使用分布式缓存可将缓存内存卸载到外部进程。

内存缓存可以存储任何对象,分布式缓存一般只能存储byte[]。二者的储存方式一般都是键值对。

2. 内存缓存

2.1 使用 IMemoryCache

先介绍下过期时间:

  • 绝对过期时间:假如设置为10s,则10s之后此缓存数据就会被清除。
  • 滑动过期时间:假如设置为3s,如果3s之内有请求过来,则缓存失效日期为当前时间再加上3s。如果在有效时间内,没请求过来,则失效。
  • 二者都进行设置:以最短的有效时间为主。假如绝对过期时间为10s,滑动过期时间为3s。如果3s没请求过来,则失效。如果每3s内就会有一个请求过来,则超过10s也会失效。

对于大多数应用IMemoryCache默认已启用,可以直接使用(否则可以手动调用AddMemoryCache)。

public class HomeController : Controller

    private IMemoryCache _cache;

    public HomeController(IMemoryCache memoryCache)
    
        _cache = memoryCache;
    

2.2 获取缓存数据 GetOrCreateGetOrCreateAsyncGet

DateTime cacheEntry;
string key="_blablabla";
//获取cache
if (!_cache.TryGetValue(key, out cacheEntry))

    //没获取到,则分配一个值
    cacheEntry = DateTime.Now;
    //设置cache策略
    var cacheEntryOptions = new MemoryCacheEntryOptions()
        //设置3s的滑动过期时间(3s内如果有请求到,则自动再延长3s)
        .SetSlidingExpiration(TimeSpan.FromSeconds(3));
    //保存到cache
    _cache.Set(key, cacheEntry, cacheEntryOptions);
    //或者直接设置绝对过期时间
    _cache.Set(key, cacheEntry, TimeSpan.FromDays(1));

获取时如果不存在则同时创建:

public async Task<IActionResult> CacheGetOrCreateAsynchronous()

    var cacheEntry = await
        _cache.GetOrCreateAsync(key, entry =>
        
            entry.SlidingExpiration = TimeSpan.FromSeconds(3);
            //也可以设置绝对过期时间(即使3s内一直有请求过来,超过10s也会过期。)
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
            return Task.FromResult(DateTime.Now);
        );

    return View("Cache", cacheEntry);

2.3 移除缓存

_cache.Remove(key)

2.4 缓存配置项 MemoryCacheEntryOptions

可以配置以下几个功能:

  • 设置过期时间:这个前面已经讲过了
  • 缓存优先级:共有四个优先级,低中高+永不移除(CacheItemPriority.NeverRemove)。当内存紧张上,系统会根据策略移除低中高优先级的缓存,不会移除NeverRemove优先级的缓存。
  • 缓存回调:可通过PostEvictionDelegate设置一个回调,当缓存失效时,此回调会在另外一个线程上运行。
public IActionResult CreateCallbackEntry()

    var cacheEntryOptions = new MemoryCacheEntryOptions()
        //永不移除
        .SetPriority(CacheItemPriority.NeverRemove)
        //设置回调
        .RegisterPostEvictionCallback(callback: EvictionCallback, state: this);

    _cache.Set(_key, DateTime.Now, cacheEntryOptions);

    return RedirectToAction("GetCallbackEntry");

private static void EvictionCallback(object key, object value,
    EvictionReason reason, object state)

    var message = $"Entry was evicted. Reason: reason.";
    ((HomeController)state)._cache.Set(_key, message);

2.5 设置缓存大小 SetSizeSizeLimit

这里的缓存大小并不是通常意义上的多少KB、MB。而是一个没有单位的相对值,因为框架并不会去计算每个缓存项的大小。

如果通过SizeLimit设置了总体缓存的大小,则必须通过SetSize设置每一个缓存项的大小。

考虑以下的配置代码:

public class MyMemoryCache 

    public MemoryCache Cache  get; private set; 
    public MyMemoryCache()
    
        Cache = new MemoryCache(new MemoryCacheOptions
        
            //设置总体缓存大小为600,无具体单位
            SizeLimit = 600
        );
    

然后,注入到容器:

public void ConfigureServices(IServiceCollection services)

    services.AddRazorPages();
    services.AddSingleton<MyMemoryCache>();

最后,设置每一个缓存项的大小:

var cacheEntryOptions = new MemoryCacheEntryOptions()
    //设置此项大小为1
    .SetSize(1)
    .SetSlidingExpiration(TimeSpan.FromSeconds(3));

_cache.Set(MyKey, cacheEntry, cacheEntryOptions);

如果每一个缓存项的大小都设置为1,则总体可以容纳600项,如果每个都是2,则可以容纳300项。

2.6 缓存依赖

缓存过期时,它的依赖项也会过期

public IActionResult CreateDependentEntries()

    var cts = new CancellationTokenSource();
    _cache.Set(CacheKeys.DependentCTS, cts);

    using (var entry = _cache.CreateEntry(CacheKeys.Parent))
    
        // expire this entry if the dependant entry expires.
        entry.Value = DateTime.Now;
        entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);

        _cache.Set(CacheKeys.Child,
            DateTime.Now,
            new CancellationChangeToken(cts.Token));
    

    return RedirectToAction("GetDependentEntries");


public IActionResult GetDependentEntries()

    return View("Dependent", new DependentViewModel
    
        ParentCachedTime = _cache.Get<DateTime?>(CacheKeys.Parent),
        ChildCachedTime = _cache.Get<DateTime?>(CacheKeys.Child),
        Message = _cache.Get<string>(CacheKeys.DependentMessage)
    );


public IActionResult RemoveChildEntry()

    _cache.Get<CancellationTokenSource>(CacheKeys.DependentCTS).Cancel();
    return RedirectToAction("GetDependentEntries");


private static void DependentEvictionCallback(object key, object value,
    EvictionReason reason, object state)

    var message = $"Parent entry was evicted. Reason: reason.";
    ((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);

2.7 其它说明

缓存过期不会在后台自动发生,当调用Get、Set、Remove等方法是才会触发一次扫描过期缓存的操作。但是CancellationTokenSource过期时也会触发这个操作。

public IActionResult CacheAutoExpiringTryGetValueSet()

    DateTime cacheEntry;

    if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
    
        cacheEntry = DateTime.Now;

        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

        var cacheEntryOptions = new MemoryCacheEntryOptions()
            .AddExpirationToken(new CancellationChangeToken(cts.Token));

        _cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions);
    

    return View("Cache", cacheEntry);

3. 分布式缓存

这个就比较多了,有基于SqlServer的、有基于Redis的、有基于NCache的。

下节将会以Redis为例进行讲解。


引用:https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/response?view=aspnetcore-6.0

在asp.netcore应用中使用imemorycache缓存(代码片段)

文章目录1.简介2.内存缓存2.1使用`IMemoryCache`2.2获取缓存数据`GetOrCreate`、`GetOrCreateAsync`和`Get`2.3移除缓存2.4缓存配置项`MemoryCacheEntryOptions`2.5设置缓存大小`SetSize`与`SizeLimi 查看详情

如何在 ASP.NET Core 中使用区域

】如何在ASP.NETCore中使用区域【英文标题】:HowtouseanAreainASP.NETCore【发布时间】:2016-07-3120:05:14【问题描述】:如何在ASP.NETCore中使用Area?我有一个需要管理部分的应用。此部分要求将其视图放置在该区域中。所有以Admin/开头的... 查看详情

从asp.netmvc迁移到asp.netcoremvc

...绍:若要迁移配置和Identity代码,请参阅将配置迁移到ASP.NETCore并迁移身份验证和IdentityASP.NETCore。在VisualStudio中创建ASP.NETMVC项目的示例以进行迁移:使用要迁移到的新ASP.NETCore项目创建新的解决方案:在ASP.NETCore3.0及更高版本的... 查看详情

在asp.netcore中使用托管服务实现后台任务

在ASP.NETCore中,后台任务作为托管服务实现。托管服务是一个类,具有实现IHostedService接口的后台任务逻辑。ASP.NETCore辅助角色服务模板可作为编写长期服务应用的起点。通过辅助角色服务模板创建的应用将在其项目文件... 查看详情

在 ASP.NET Core 应用程序中使用多个 HttpClient 对象

】在ASP.NETCore应用程序中使用多个HttpClient对象【英文标题】:UsingmultipleHttpClientobjectsinanASP.NETCoreapplication【发布时间】:2020-01-0310:09:44【问题描述】:当有多个客户端(公司)使用ASP.NETCore应用程序并且必须在每个公司的ASP.NET应... 查看详情

使用playwright对asp.netcore应用执行功能测试

...部署好的Web应用。其实,开发人员也可以使用它在ASP.NETCore应用程序中进行功能测试。功能测试功能测试是从用户角度编写,用于基于其要求验证系统的正确性。由于功能测试在系统级别运行,所以可能需要一定程度... 查看详情

在asp.netcore中使用ihttpclientfactory发出http请求

参考技术A可以注册IHttpClientFactory并将其用于配置和创建应用中的HttpClient实例。IHttpClientFactory的优势如下:查看或下载示例代码(如何下载)。此主题版本中的示例代码使用System.Text.Json来对HTTP响应中返回的JSON内容进行反序列化... 查看详情

netcore体系-web应用程序7asp.netcore日志组件

日志介绍Logging的使用1.appsettings.json中Logging的介绍Logging的配置信息是保存在appsettings.json配置文件中的。因为之前介绍配置文件的时候我们使用的是appsettings.Development.json这个文件,所以在介绍Logging的时候我们也用它吧。通过上图... 查看详情

asp.netcore中托管spa应用

...景,我们需要一个前后端分离的应用,服务端API使用ASP.NETCore开发,前端有两套,一个是用于所有用户的客户端,另一个是给管理员使用的管理后台,使用asp.netcore的hosting作为后端+前端的web服务器。应为默认情况下没有开启hostin... 查看详情

在asp.netcore中使用serilog使用fluentd将日志写入elasticsearch(代码片段)

在ASP.NETCore中使用Serilog使用Fluentd将日志写入Elasticsearch原文来自:https://andrewlock.net/writing-logs-to-elasticsearch-with-fluentd-using-serilog-in-asp-net-core/对于在Kubernetes中运行的应用程序,将日志消息存储在一个中心位置 查看详情

如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

】如何使用EFCore在ASP.NETCore中取消应用迁移【英文标题】:HowtounapplyamigrationinASP.NETCorewithEFCore【发布时间】:2016-11-0615:25:03【问题描述】:当我在VS2015中使用EFCore的ASP.NETCore项目运行PM&gt;Remove-Migration-contextBloggingContext时,我收... 查看详情

在asp.netcore应用中使用imemorycache缓存(代码片段)

...缩性。Caching适用于不经常更改且生成成本高的数据。ASP.NETCore支持多个不同的缓存。最简单的缓存基于IMemoryCache。IMemoryCache属于内存缓存,存在于应用内部。如果使用内存缓存,后续请求需要都请求到这一个应用上,... 查看详情

在asp.netcore应用中使用imemorycache缓存(代码片段)

...缩性。Caching适用于不经常更改且生成成本高的数据。ASP.NETCore支持多个不同的缓存。最简单的缓存基于IMemoryCache。IMemoryCache属于内存缓存,存在于应用内部。如果使用内存缓存,后续请求需要都请求到这一个应用上,... 查看详情

在asp.netcore应用中使用imemorycache缓存(代码片段)

...缩性。Caching适用于不经常更改且生成成本高的数据。ASP.NETCore支持多个不同的缓存。最简单的缓存基于IMemoryCache。IMemoryCache属于内存缓存,存在于应用内部。如果使用内存缓存,后续请求需要都请求到这一个应用上,... 查看详情

在 ASP.Net Core 中使用 SharedLocalizer 和 javascript

】在ASP.NetCore中使用SharedLocalizer和javascript【英文标题】:UsingSharedLocalizerandjavascriptinASP.NetCore【发布时间】:2019-03-1501:14:50【问题描述】:我正在使用asp.netcore2.0来开发我的MVC应用程序。但是,我在视图中使用SharedLocalizer。我使用... 查看详情

在带有数据库的 ASP.NET Core 5.0 应用程序中使用 Serilog 实现日志记录

】在带有数据库的ASP.NETCore5.0应用程序中使用Serilog实现日志记录【英文标题】:ImplementLoggingUsingSerilogInASP.NETCore5.0ApplicationWithDatabase【发布时间】:2021-09-3023:02:38【问题描述】:在我的asp.netcore5.0应用程序中,每当我尝试使用serilo... 查看详情

如何在 ASP.NET Core 中使用 npm

】如何在ASP.NETCore中使用npm【英文标题】:HowtousenpmwithASP.NETCore【发布时间】:2016-10-2211:26:20【问题描述】:我正在使用npm来管理我的ASP.NETCore应用程序所需的jQuery、Bootstrap、FontAwesome和类似的客户端库。对我有用的方法首先是在... 查看详情

如何在 asp.net core 2.1 中使用 net.tcp 服务

】如何在asp.netcore2.1中使用net.tcp服务【英文标题】:HowdoIconsumeanet.tcpserviceinasp.netcore2.1【发布时间】:2019-04-0212:26:44【问题描述】:我正在构建一个asp.netcore2.1Web应用程序,我需要调用一个旧的net.tcp端点来获取有关预订的详细信... 查看详情