.NET 9
引入了 HybridCache
,这是一个新的高性能、分布式就绪的内存缓存实现,旨在为现代 Web
应用提供更高效的数据缓存机制。它结合了本地缓存(如 IMemoryCache
)和分布式缓存(如 Redis、Garnet、SQL Server
)的优点,支持自动分级存储和异步刷新,同时具备高并发下的性能优势。
特点
- 混合缓存架构:结合本地内存缓存与分布式缓存,减少网络往返。
- 自动分层:热数据保留在本地,冷数据回退到分布式存储。
- 异步刷新:避免缓存击穿,提升用户体验。
- 可扩展性:支持自定义序列化、键生成策略和分布式缓存提供者。
- 集成 DI:开箱即用,支持依赖注入。
🚀 使用示例
示例1:默认方式使用
1.1 安装 nuget 包(如果尚未引入)
新建 asp.net core9 webapi
项目,添加 nuget
包:
dotnet add package Microsoft.Extensions.Caching.Hybrid
nuget
包下载,https://www.nuget.org/packages/Microsoft.Extensions.Caching.Hybrid
1.2 注册 HybridCache
服务
在 Program.cs
中注册:
var builder = WebApplication.CreateBuilder(args);// 添加 HybridCache
builder.Services.AddHybridCache();var app = builder.Build();
1.3 使用 IHybridCache
缓存数据
以下是一个简单的控制器使用示例:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Hybrid;[ApiController]
[Route("[controller]")]
public class WeatherForecastController(IHybridCache cache) : ControllerBase
{[HttpGet]public async Task<IActionResult> Get(){var key = "weather_data";var result = await cache.GetOrCreateAsync(key, async (token) =>{// 模拟耗时操作,例如从数据库或 API 获取数据await Task.Delay(100, token);return new[] { "Sunny", "Cloudy", "Rainy" };});return Ok(result);}
}
1.4 配置 HybridCache
(可选)
你可以在 appsettings.json
或代码中配置缓存行为:
builder.Services.AddHybridCache(options =>
{options.LocalCacheSizeLimit = 1024; // 设置本地缓存最大条目数options.DistributedCacheEntryOptions = new DistributedCacheEntryOptions{AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)};
});
说明:上面的配置项,可依据实际情况自行调整。
示例2:注册 Garnet 为分布式缓存提供者
在 ASP.NET Core 9
中,你可以将 HybridCache
配置为使用 Garnet
作为其底层的分布式缓存提供者。Garnet
是微软开发的一个高性能、兼容 Redis
协议的键值存储系统,适用于需要高吞吐和低延迟的场景。
Garnet
官网,https://microsoft.github.io/garnet/
✅ 使用 HybridCache + Garnet
的步骤:
2.1 安装必要的 NuGet 包
dotnet add package Microsoft.Extensions.Caching.Hybrid
dotnet add package Garnet.Client
2.2 启动 Garnet 服务器(本地或远程)
确保你已经安装并运行了 Garnet
服务,可以通过以下方式启动:
# 假设已编译 Garnet 并进入目录
cd Garnet/bin/Release/net7.0
./garnet-server --port 6380
2.3 注册 Garnet 客户端和服务
你需要创建一个自定义的 IDistributedCache
实现来使用 Garnet
,或者使用社区提供的适配器。
下面是一个简单示例,展示如何注册 Garnet
作为分布式缓存提供者:
- a. 创建
Garnet
分布式缓存实现
using Garnet.Client;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;public class GarnetDistributedCache : IDistributedCache
{private readonly GarnetClient _client;public GarnetDistributedCache(GarnetClient client) => _client = client;public byte[] Get(string key) => _client.GetAsync(key).Result;public async Task<byte[]> GetAsync(string key, CancellationToken ct = default)=> await _client.GetAsync(key, ct);public void Set(string key, byte[] value, DistributedCacheEntryOptions options)=> _client.SetAsync(key, value, GetExpiryFromOptions(options)).Wait();public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken ct = default)=> await _client.SetAsync(key, value, GetExpiryFromOptions(options), ct);public void Refresh(string key)=> _client.KeyExpireAsync(key, TimeSpan.FromMinutes(5)).Wait(); // 默认刷新为 5 分钟public async Task RefreshAsync(string key, CancellationToken ct = default){var ttl = await _client.KeyTtlAsync(key, ct); // 获取当前剩余 TTLif (ttl.HasValue && ttl.Value > TimeSpan.Zero){// 若已有 TTL,刷新为相同的持续时间await _client.KeyExpireAsync(key, ttl.Value, ct);}else{// 否则设置一个默认 TTL(可自定义)await _client.KeyExpireAsync(key, TimeSpan.FromMinutes(5), ct);}}public void Remove(string key) => _client.DeleteAsync(key).Wait();public Task RemoveAsync(string key, CancellationToken ct) => _client.DeleteAsync(key, ct);// 根据 DistributedCacheEntryOptions 获取过期时间private TimeSpan? GetExpiryFromOptions(DistributedCacheEntryOptions options){if (options.AbsoluteExpirationRelativeToNow.HasValue)return options.AbsoluteExpirationRelativeToNow.Value;else if (options.SlidingExpiration.HasValue)return options.SlidingExpiration.Value;return null;}
}
- b. 注册
Garnet
客户端和缓存服务
var builder = WebApplication.CreateBuilder(args);// 添加 Garnet 客户端
builder.Services.AddSingleton<GarnetClient>(sp =>
{var client = new GarnetClient("localhost", 6380);client.Connect();return client;
});// 添加 Garnet 缓存实现
builder.Services.AddSingleton<IDistributedCache, GarnetDistributedCache>();// 添加 HybridCache,并使用 Garnet 作为分布式缓存后端
builder.Services.AddHybridCache(options =>
{options.LocalCacheSizeLimit = 500;options.LocalTtl = TimeSpan.FromSeconds(30);options.UseDistributedCache = true;options.DistributedTtl = TimeSpan.FromMinutes(5);options.UseSlidingExpiration = true; // 自动调用 Refresh/RefreshAsync
});
在注册 HybridCache
时启用 滑动过期策略
,这样,当某个缓存项被访问时,系统会自动调用 RefreshAsync
方法来更新其在 Garnet
中的 TTL
。
2.4 在应用中使用 HybridCache
在控制器中使用缓存方式与之前一致。
[ApiController]
[Route("[controller]")]
public class SampleController(IHybridCache cache) : ControllerBase
{[HttpGet]public async Task<IActionResult> GetData(){var data = await cache.GetOrCreateAsync("sample-key", async (token) =>{// 模拟耗时获取数据await Task.Delay(200, token);return new[] { "Data1", "Data2" };});return Ok(data);}
}
🧠 小贴士
- 性能优化:可以结合
HybridCache
的LocalTtl
和DistributedTtl
控制缓存生命周期。 - 序列化配置:可通过
AddHybridCache()
的选项自定义ISerializer
,例如使用System.Text.Json
或 MessagePack。 Garnet
集群支持:如果使用集群模式,请确保客户端正确配置路由逻辑。
在 ASP.NET Core 9
的 HybridCache
中,LocalTtl
和 DistributedTtl
是两个关键配置项,用于控制缓存数据的生命周期。它们分别作用于 本地缓存层
和分布式缓存层
,使得你可以更精细地管理缓存的有效期。
🔍 配置说明
LocalTtl
(本地缓存过期时间)
- 含义:设置缓存项在本地内存中保留的最大时间。
- 用途:确保频繁访问的数据保留在本地,提高响应速度,同时避免本地缓存长时间不更新。
- 类型:
TimeSpan
- 示例:
services.AddHybridCache(options =>
{options.LocalTtl = TimeSpan.FromSeconds(30); // 本地缓存最多保留 30 秒
});
DistributedTtl
(分布式缓存过期时间)
- 含义:设置缓存项在分布式缓存中的最大存活时间。
- 用途:控制整个缓存系统的最终一致性,适用于跨节点共享缓存的场景。
- 类型:
TimeSpan
- 示例:
services.AddHybridCache(options =>
{options.DistributedTtl = TimeSpan.FromMinutes(5); // 分布式缓存最多保留 5 分钟
});
🔄 即使本地缓存已过期,系统也会尝试从分布式缓存加载最新数据;若分布式缓存也过期,则重新生成并写回两级缓存。
⚙️ 典型组合策略
场景 | LocalTtl | DistributedTtl | 说明 |
---|---|---|---|
高频读取、容忍短时旧数据 | 30s | 5min | 提高性能,减少后端压力 |
数据变化频繁、要求较新 | 5s | 30s | 快速更新本地缓存,保持整体一致性 |
只读数据、极少变更 | null(永不过期) | 24h | 本地永久缓存 + 分布式定期更新 |
🧠 使用技巧
- 设置
LocalTtl = null
表示本地缓存永不自动过期(仍可能被逐出以节省内存)。 - 设置
DistributedTtl = null
表示分布式缓存项不会自动删除。 - 如果只设置了
LocalTtl
而未设置DistributedTtl
,则分布式缓存默认与本地一致。 - 可结合
AbsoluteExpirationRelativeToNow
或SlidingExpiration
等高级策略进行更复杂的控制。
通过合理配置 LocalTtl
和 DistributedTtl
,你可以灵活控制 HybridCache
的行为,实现以下目标:
- 提升高频访问性能(利用本地缓存)
- 减少对后端系统的冲击(利用分布式缓存)
- 控制数据新鲜度(避免缓存脏读)
这是 HybridCache
强大灵活性的重要体现之一。
✅ 总结
HybridCache
是 .NET 9
的一大亮点,适用于需要高性能、低延迟和分布式能力的现代应用。通过简单配置即可获得 本地 + 分布式
的双重优势,是替代传统 IMemoryCache
和 IDistributedCache
的理想选择。
通过将 HybridCache
与 Garnet
结合,你可以构建一个高性能、低延迟、支持分布式部署的缓存架构。这非常适合用于 微服务、API 网关、电商推荐
等对性能要求极高的场景。