ASP.NET Core 中的缓存概述

注意

此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

对于当前版本,请参阅此文的 .NET 8 版本

作者:Rick AndersonTom Dykstra

内存中缓存

内存中缓存使用服务器内存来存储缓存的数据。 这种类型的缓存适用于使用会话亲和性的单个服务器或多个服务器。 会话亲和性也称为“粘滞会话”。 会话亲和性是指来自客户端的请求总是路由到同一个服务器进行处理。

有关详细信息,请参阅 ASP.NET Core 中的内存中缓存排查 Azure 应用程序网关会话亲和性问题

分布式缓存

当应用托管在云或服务器场中时,使用分布式缓存存储数据。 缓存在处理请求的服务器之间共享。 如果客户端的缓存数据可用,则客户端可以提交由组中的任何服务器处理的请求。 ASP.NET Core 适用于 SQL Server、RedisNCache 分布式缓存。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存

HybridCache

HybridCache API 弥补了 IDistributedCacheIMemoryCache API 中的一些差距。 HybridCache 是一个抽象类,其默认实现可处理保存到缓存和从缓存中检索的大多数方面。

功能

HybridCache 具有其他 API 没有的以下功能:

  • 用于进程内和进程外缓存的统一 API。

    HybridCache 旨在作为现有 IDistributedCacheIMemoryCache 的即插即用替代品,并且提供了一个简单的 API 用于添加新的缓存代码。 如果应用具有 IDistributedCache 实现,HybridCache 服务将其用于辅助缓存。 此两级缓存策略允许 HybridCache 提供内存中缓存的速度以及分布式或永久性缓存的持久性。

  • 踩踏防护。

    当经常使用的缓存条目被撤销,并且过多的请求尝试同时重新填充同一缓存条目时,会发生缓存踩踏。 HybridCache 合并并发操作,确保给定响应的所有请求都等待第一个请求填充缓存。

  • 可配置的序列化。

    序列化在注册服务的过程中配置,支持通过 WithSerializerWithSerializerFactory 方法进行特定于类型的通用序列化程序(通过 AddHybridCache 调用链接)。 默认情况下,服务在内部处理 stringbyte[],并使用 System.Text.Json 处理其他所有内容。 可以为其他类型的序列化程序(例如 protobuf 或 XML)配置它。

要了解 HybridCache API 的相对简单性,请将使用它的代码与使用 IDistributedCache 的代码进行比较。 下面是使用 IDistributedCache 的示例:

public class SomeService(IDistributedCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
        var bytes = await cache.GetAsync(key, token); // Try to get from cache.
        SomeInformation info;
        if (bytes is null)
        {
            // Cache miss; get the data from the real source.
            info = await SomeExpensiveOperationAsync(name, id, token);

            // Serialize and cache it.
            bytes = SomeSerializer.Serialize(info);
            await cache.SetAsync(key, bytes, token);
        }
        else
        {
            // Cache hit; deserialize it.
            info = SomeSerializer.Deserialize<SomeInformation>(bytes);
        }
        return info;
    }

    // This is the work we're trying to cache.
    private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
        CancellationToken token = default)
    { /* ... */ }
}

每次都要处理很多工作,包括序列化之类的操作。 在缓存缺失的情况下,最终可能会有多个并发线程,这些线程均会出现缓存缺失、提取基础数据、对数据执行序列化,并将该数据发送到缓存。

下面是使用 HybridCache 的等效代码:

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // Unique key for this entry.
            async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
            token: token
        );
    }
}

该代码更简单,并且库提供了踩踏防护以及 IDistributedCache 未提供的其他功能。

兼容性

该库支持较旧的 .NET 运行时,最低支持 .NET Framework 4.7.2 和 .NET Standard 2.0。

其他资源

有关更多信息,请参见以下资源:

响应缓存

响应缓存中间件:

  • 启用基于 HTTP 缓存头的缓存服务器响应。 实现标准 HTTP 缓存语义。 像代理一样基于 HTTP 缓存标头进行缓存。
  • 通过对 Razor Pages 等 UI 应用没有好处,因为浏览器通常会设置阻止缓存的请求头。 ASP.NET Core 7.0 及更高版本中提供的输出缓存将有利于 UI 应用。 使用输出缓存,配置可决定了应独立于 HTTP 标头缓存的内容。
  • 对于来自满足缓存条件的客户端的公共 GET 或 HEAD API 请求可能有用。

若要测试响应缓存,请使用 Fiddler 或可显式设置请求头的其他工具。 显式设置标头是测试缓存的首选项。 有关详细信息,请参阅疑难解答

有关详细信息,请参阅 ASP.NET Core 中的响应缓存

输出缓存

输出缓存中间件支持 HTTP 响应的缓存。 输出缓存与响应缓存的不同之处包括以下方面:

  • 缓存行为可在服务器上配置。

    响应缓存行为由 HTTP 标头定义。 例如,使用 Chrome 或 Edge 访问网站时,浏览器会自动发送 Cache-control: max-age=0 标头。 此标头将有效地禁用响应缓存,因为服务器遵循客户端提供的说明。 即使服务器有新的缓存响应,也会为每个请求返回新的响应。 使用输出缓存时,客户端不会替代你在服务器上配置的缓存行为。

  • 缓存存储介质是可扩展的。

    默认情况下使用内存。 响应缓存仅限于内存。

  • 可以通过编程方式使选定的缓存条目无效。

    响应缓存对 HTTP 标头的依赖导致只有几个选项可以使缓存条目失效。

  • 资源锁定可降低缓存踩踏和惊群的风险。

    当经常使用的缓存条目被撤销,并且过多的请求尝试同时重新填充同一缓存条目时,会发生缓存踩踏。 惊群类似于:针对缓存条目中尚未存在的相同响应的突发请求。 资源锁定可确保给定响应的所有请求都等待第一个请求填充缓存。 响应缓存没有资源锁定功能。

  • 缓存重新验证可最大程度地减少带宽使用。

    缓存重新验证意味着服务器可以返回 304 Not Modified HTTP 状态代码,而不是缓存的响应正文。 此状态代码通知客户端,对请求的响应与之前接收的内容相同。 响应缓存不执行缓存重新验证。

有关详细信息,请参阅 ASP.NET Core 中的输出缓存中间件

缓存标记帮助程序

使用缓存标记帮助程序缓存来自 MVC 视图或 Razor 页面的内容。 缓存标记帮助程序使用内存中缓存来存储数据。

有关详细信息,请参阅 ASP.NET Core MVC 中的缓存标记帮助程序

分布式缓存标记帮助程序

使用分布式缓存标记帮助程序在分布式云或 Web 场方案中缓存来自 MVC 视图或 Razor 页面的内容。 分布式缓存标记帮助程序使用 SQL Server、RedisNCache 来存储数据。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存标记帮助程序

内存中缓存

内存中缓存使用服务器内存来存储缓存的数据。 这种类型的缓存适用于使用会话亲和性的单个服务器或多个服务器。 会话亲和性也称为“粘滞会话”。 会话亲和性是指来自客户端的请求总是路由到同一个服务器进行处理。

有关详细信息,请参阅 ASP.NET Core 中的内存中缓存排查 Azure 应用程序网关会话亲和性问题

分布式缓存

当应用托管在云或服务器场中时,使用分布式缓存存储数据。 缓存在处理请求的服务器之间共享。 如果客户端的缓存数据可用,则客户端可以提交由组中的任何服务器处理的请求。 ASP.NET Core 适用于 SQL Server、RedisNCache 分布式缓存。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存

HybridCache

HybridCache API 弥补了 IDistributedCacheIMemoryCache API 中的一些差距。 HybridCache 是一个抽象类,其默认实现可处理保存到缓存和从缓存中检索的大多数方面。

功能

HybridCache 具有其他 API 没有的以下功能:

  • 用于进程内和进程外缓存的统一 API。

    HybridCache 旨在作为现有 IDistributedCacheIMemoryCache 的即插即用替代品,并且提供了一个简单的 API 用于添加新的缓存代码。 如果应用具有 IDistributedCache 实现,HybridCache 服务将其用于辅助缓存。 此两级缓存策略允许 HybridCache 提供内存中缓存的速度以及分布式或永久性缓存的持久性。

  • 踩踏防护。

    当经常使用的缓存条目被撤销,并且过多的请求尝试同时重新填充同一缓存条目时,会发生缓存踩踏。 HybridCache 合并并发操作,确保给定响应的所有请求都等待第一个请求填充缓存。

  • 可配置的序列化。

    序列化在注册服务的过程中配置,支持通过 WithSerializerWithSerializerFactory 方法进行特定于类型的通用序列化程序(通过 AddHybridCache 调用链接)。 默认情况下,服务在内部处理 stringbyte[],并使用 System.Text.Json 处理其他所有内容。 可以为其他类型的序列化程序(例如 protobuf 或 XML)配置它。

要了解 HybridCache API 的相对简单性,请将使用它的代码与使用 IDistributedCache 的代码进行比较。 下面是使用 IDistributedCache 的示例:

public class SomeService(IDistributedCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
        var bytes = await cache.GetAsync(key, token); // Try to get from cache.
        SomeInformation info;
        if (bytes is null)
        {
            // Cache miss; get the data from the real source.
            info = await SomeExpensiveOperationAsync(name, id, token);

            // Serialize and cache it.
            bytes = SomeSerializer.Serialize(info);
            await cache.SetAsync(key, bytes, token);
        }
        else
        {
            // Cache hit; deserialize it.
            info = SomeSerializer.Deserialize<SomeInformation>(bytes);
        }
        return info;
    }

    // This is the work we're trying to cache.
    private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
        CancellationToken token = default)
    { /* ... */ }
}

每次都要处理很多工作,包括序列化之类的操作。 在缓存缺失的情况下,最终可能会有多个并发线程,这些线程均会出现缓存缺失、提取基础数据、对数据执行序列化,并将该数据发送到缓存。

下面是使用 HybridCache 的等效代码:

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // Unique key for this entry.
            async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
            token: token
        );
    }
}

该代码更简单,并且库提供了踩踏防护以及 IDistributedCache 未提供的其他功能。

兼容性

该库支持较旧的 .NET 运行时,最低支持 .NET Framework 4.7.2 和 .NET Standard 2.0。

其他资源

有关更多信息,请参见以下资源:

缓存标记帮助程序

使用缓存标记帮助程序缓存来自 MVC 视图或 Razor 页面的内容。 缓存标记帮助程序使用内存中缓存来存储数据。

有关详细信息,请参阅 ASP.NET Core MVC 中的缓存标记帮助程序

分布式缓存标记帮助程序

使用分布式缓存标记帮助程序在分布式云或 Web 场方案中缓存来自 MVC 视图或 Razor 页面的内容。 分布式缓存标记帮助程序使用 SQL Server、RedisNCache 来存储数据。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存标记帮助程序

响应缓存

响应缓存中间件:

  • 启用基于 HTTP 缓存头的缓存服务器响应。 实现标准 HTTP 缓存语义。 像代理一样基于 HTTP 缓存标头进行缓存。
  • 通过对 Razor Pages 等 UI 应用没有好处,因为浏览器通常会设置阻止缓存的请求头。 ASP.NET Core 7.0 及更高版本中提供的输出缓存将有利于 UI 应用。 使用输出缓存,配置可决定了应独立于 HTTP 标头缓存的内容。
  • 对于来自满足缓存条件的客户端的公共 GET 或 HEAD API 请求可能有用。

若要测试响应缓存,请使用 Fiddler 或可显式设置请求头的其他工具。 显式设置标头是测试缓存的首选项。 有关详细信息,请参阅疑难解答

输出缓存

输出缓存中间件支持 HTTP 响应的缓存。 输出缓存与响应缓存的不同之处包括以下方面:

  • 缓存行为可在服务器上配置。

    响应缓存行为由 HTTP 标头定义。 例如,使用 Chrome 或 Edge 访问网站时,浏览器会自动发送 Cache-control: max-age=0 标头。 此标头将有效地禁用响应缓存,因为服务器遵循客户端提供的说明。 即使服务器有新的缓存响应,也会为每个请求返回新的响应。 使用输出缓存时,客户端不会替代你在服务器上配置的缓存行为。

  • 缓存存储介质是可扩展的。

    默认情况下使用内存。 响应缓存仅限于内存。

  • 可以通过编程方式使选定的缓存条目无效。

    响应缓存对 HTTP 标头的依赖导致只有几个选项可以使缓存条目失效。

  • 资源锁定可降低缓存踩踏和惊群的风险。

    当经常使用的缓存条目被撤销,并且过多的请求尝试同时重新填充同一缓存条目时,会发生缓存踩踏。 惊群类似于:针对缓存条目中尚未存在的相同响应的突发请求。 资源锁定可确保给定响应的所有请求都等待第一个请求填充缓存。 响应缓存没有资源锁定功能。

  • 缓存重新验证可最大程度地减少带宽使用。

    缓存重新验证意味着服务器可以返回 304 Not Modified HTTP 状态代码,而不是缓存的响应正文。 此状态代码通知客户端,对请求的响应与之前接收的内容相同。 响应缓存不执行缓存重新验证。

内存中缓存

内存中缓存使用服务器内存来存储缓存的数据。 这种类型的缓存适用于使用会话亲和性的单个服务器或多个服务器。 会话亲和性也称为“粘滞会话”。 会话亲和性是指来自客户端的请求总是路由到同一个服务器进行处理。

有关详细信息,请参阅 ASP.NET Core 中的内存中缓存排查 Azure 应用程序网关会话亲和性问题

分布式缓存

当应用托管在云或服务器场中时,使用分布式缓存存储数据。 缓存在处理请求的服务器之间共享。 如果客户端的缓存数据可用,则客户端可以提交由组中的任何服务器处理的请求。 ASP.NET Core 适用于 SQL Server、RedisNCache 分布式缓存。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存

HybridCache

HybridCache API 弥补了 IDistributedCacheIMemoryCache API 中的一些差距。 HybridCache 是一个抽象类,其默认实现可处理保存到缓存和从缓存中检索的大多数方面。

功能

HybridCache 具有其他 API 没有的以下功能:

  • 用于进程内和进程外缓存的统一 API。

    HybridCache 旨在作为现有 IDistributedCacheIMemoryCache 的即插即用替代品,并且提供了一个简单的 API 用于添加新的缓存代码。 如果应用具有 IDistributedCache 实现,HybridCache 服务将其用于辅助缓存。 此两级缓存策略允许 HybridCache 提供内存中缓存的速度以及分布式或永久性缓存的持久性。

  • 踩踏防护。

    当经常使用的缓存条目被撤销,并且过多的请求尝试同时重新填充同一缓存条目时,会发生缓存踩踏。 HybridCache 合并并发操作,确保给定响应的所有请求都等待第一个请求填充缓存。

  • 可配置的序列化。

    序列化在注册服务的过程中配置,支持通过 WithSerializerWithSerializerFactory 方法进行特定于类型的通用序列化程序(通过 AddHybridCache 调用链接)。 默认情况下,服务在内部处理 stringbyte[],并使用 System.Text.Json 处理其他所有内容。 可以为其他类型的序列化程序(例如 protobuf 或 XML)配置它。

要了解 HybridCache API 的相对简单性,请将使用它的代码与使用 IDistributedCache 的代码进行比较。 下面是使用 IDistributedCache 的示例:

public class SomeService(IDistributedCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
        var bytes = await cache.GetAsync(key, token); // Try to get from cache.
        SomeInformation info;
        if (bytes is null)
        {
            // Cache miss; get the data from the real source.
            info = await SomeExpensiveOperationAsync(name, id, token);

            // Serialize and cache it.
            bytes = SomeSerializer.Serialize(info);
            await cache.SetAsync(key, bytes, token);
        }
        else
        {
            // Cache hit; deserialize it.
            info = SomeSerializer.Deserialize<SomeInformation>(bytes);
        }
        return info;
    }

    // This is the work we're trying to cache.
    private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
        CancellationToken token = default)
    { /* ... */ }
}

每次都要处理很多工作,包括序列化之类的操作。 在缓存缺失的情况下,最终可能会有多个并发线程,这些线程均会出现缓存缺失、提取基础数据、对数据执行序列化,并将该数据发送到缓存。

下面是使用 HybridCache 的等效代码:

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // Unique key for this entry.
            async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
            token: token
        );
    }
}

该代码更简单,并且库提供了踩踏防护以及 IDistributedCache 未提供的其他功能。

兼容性

该库支持较旧的 .NET 运行时,最低支持 .NET Framework 4.7.2 和 .NET Standard 2.0。

其他资源

有关更多信息,请参见以下资源:

缓存标记帮助程序

使用缓存标记帮助程序缓存来自 MVC 视图或 Razor 页面的内容。 缓存标记帮助程序使用内存中缓存来存储数据。

有关详细信息,请参阅 ASP.NET Core MVC 中的缓存标记帮助程序

分布式缓存标记帮助程序

使用分布式缓存标记帮助程序在分布式云或 Web 场方案中缓存来自 MVC 视图或 Razor 页面的内容。 分布式缓存标记帮助程序使用 SQL Server、RedisNCache 来存储数据。

有关详细信息,请参阅 ASP.NET Core 中的分布式缓存标记帮助程序

响应缓存

响应缓存中间件:

  • 启用基于 HTTP 缓存头的缓存服务器响应。 实现标准 HTTP 缓存语义。 像代理一样基于 HTTP 缓存标头进行缓存。
  • 通过对 Razor Pages 等 UI 应用没有好处,因为浏览器通常会设置阻止缓存的请求头。 ASP.NET Core 7.0 及更高版本中提供的输出缓存将有利于 UI 应用。 使用输出缓存,配置可决定了应独立于 HTTP 标头缓存的内容。
  • 对于来自满足缓存条件的客户端的公共 GET 或 HEAD API 请求可能有用。

若要测试响应缓存,请使用 Fiddler 或可显式设置请求头的其他工具。 显式设置标头是测试缓存的首选项。 有关详细信息,请参阅疑难解答

输出缓存

输出缓存在 .NET 7 及更高版本中可用。