精选 款 .NET 开源、实用的缓存框架,帮助开发者更轻松地处理系统缓存! 精选 5 款 .NET 开源、实用的缓存框架帮助开发者更轻松地处理系统缓存为什么需要缓存框架在现代 .NET 应用中缓存是提升性能的关键手段。无论是减少数据库查询、降低 API 响应时间还是应对高并发场景合理的缓存策略都能让系统如虎添翼。但手动管理缓存例如自己写Dictionary或MemoryCache包装器往往会陷入“重复造轮子”的困境缺乏过期策略、缺少分布式支持、难以扩展。幸运的是.NET 生态中有大量开源的缓存框架它们封装了常见模式如 LRU、滑动过期、缓存穿透防护等让开发者只需几行代码就能实现高性能缓存。本文将精选 5 款实用、轻量且活跃维护的 .NET 缓存框架并通过代码示例展示如何快速上手。—## 1. FusionCache现代、优雅的混合缓存库FusionCache 是一个 .NET 缓存抽象库它支持内存缓存 分布式缓存的混合模式并内置了“缓存 stampede 防护”防止多个请求同时重建缓存和“软/硬过期”机制。如果你需要一个既简单又强大的缓存方案FusionCache 是绝佳选择。### 安装bashdotnet add package ZiggyCreatures.FusionCache### 代码示例基本使用与高级特性csharpusing ZiggyCreatures.Caching.Fusion;// 1. 创建 FusionCache 实例通常通过 DI 注入var cache new FusionCache(new FusionCacheOptions(){ CacheName MyAppCache, DefaultEntryOptions new FusionCacheEntryOptions { Duration TimeSpan.FromMinutes(5), // 默认过期时间 IsFailSafeEnabled true, // 启用安全防护缓存失败时使用旧值 FailSafeMaxDuration TimeSpan.FromHours(2) // 安全模式下最大使用旧值时间 }});// 2. 使用 GetOrSet 方法若缓存存在则返回否则执行回调并缓存结果async TaskUser GetUserAsync(int userId){ // 通过工厂方法获取数据避免缓存穿透 return await cache.GetOrSetAsync( $user:{userId}, async (ctx) { // 模拟从数据库获取用户 var user await _dbContext.Users.FindAsync(userId); if (user null) throw new KeyNotFoundException(User not found); // FusionCache 会自动处理异常 return user; }, options options.SetDuration(TimeSpan.FromMinutes(10)) // 可以动态设置过期时间 );}// 3. 手动设置和获取缓存适合有预加载场景await cache.SetAsync(config:theme, dark, TimeSpan.FromHours(1));var theme await cache.GetOrDefaultAsyncstring(config:theme, light); // 默认值关键点FusionCache 自动处理了缓存击穿和雪崩问题你无需编写额外的锁或双重检查逻辑。—## 2. EasyCaching支持多种后端的缓存抽象层EasyCaching 是一个“缓存即服务”框架它抽象了内存、Redis、SQLite、Memcached 等多种后端并提供一致的 API。如果你的系统需要灵活切换缓存存储例如从本地内存切换到 Redis 集群EasyCaching 能让迁移成本降到最低。### 安装bashdotnet add package EasyCaching.InMemorydotnet add package EasyCaching.Redis### 代码示例多后端缓存切换csharpusing EasyCaching.Core;// 1. 配置通常在 Startup.cs 或 Program.cs 中services.AddEasyCaching(options { // 使用内存缓存作为默认后端 options.UseInMemory(default, config { config.DBConfig new InMemoryCachingOptions { ExpirationScanFrequency TimeSpan.FromMinutes(1) }; }); // 同时配置 Redis 作为二级缓存 options.UseRedis(redis, config { config.DBConfig.Endpoints.Add(new ServerEndPoint(localhost, 6379)); config.DBConfig.Database 0; });});// 2. 在业务代码中使用public class ProductService{ private readonly IEasyCachingProvider _cacheProvider; public ProductService(IEasyCachingProviderFactory factory) { // 通过工厂获取指定名称的缓存提供器 _cacheProvider factory.GetCachingProvider(default); } public async TaskProduct GetProductAsync(int id) { var cacheKey $product:{id}; // 尝试从缓存获取 var cached await _cacheProvider.GetAsyncProduct(cacheKey); if (cached.HasValue) return cached.Value; // 缓存未命中从数据库获取 var product await _db.Products.FindAsync(id); if (product ! null) { // 设置缓存支持过期时间 await _cacheProvider.SetAsync(cacheKey, product, TimeSpan.FromMinutes(30)); } return product; }}特色EasyCaching 提供了ICachingProvider接口你可以用同一套代码操作内存、Redis 甚至分布式缓存且支持批量操作如SetAllAsync、GetAllAsync。—## 3. LazyCache轻量级、线程安全的缓存包装器LazyCache 是一个极简的缓存库它基于MemoryCache并提供了“延迟初始化 线程安全”的封装。它的核心思想是当多个线程同时请求一个未缓存的键时只有一个线程会执行加载逻辑其他线程等待结果——这避免了重复计算。### 安装bashdotnet add package LazyCache### 代码示例懒加载与过期策略csharpusing LazyCache;using Microsoft.Extensions.Caching.Memory;// 1. 创建缓存服务推荐通过 DI 注入 IAppCacheIAppCache cache new CachingService();// 2. 线程安全的缓存获取自动处理并发async TaskWeatherForecast GetWeatherAsync(string city){ // 使用 GetOrAddAsync回调只会在缓存未命中时执行一次 return await cache.GetOrAddAsync( $weather:{city}, async () { // 模拟耗时的 API 调用例如调用天气服务 await Task.Delay(1000); return new WeatherForecast { City city, Temperature Random.Shared.Next(-10, 40), Date DateTime.Now }; }, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow TimeSpan.FromMinutes(5), // 绝对过期 SlidingExpiration TimeSpan.FromMinutes(1) // 滑动过期每次访问延长1分钟 } );}// 3. 验证并发安全性多个线程同时请求同一个 keyvar tasks Enumerable.Range(0, 10).Select(_ GetWeatherAsync(Beijing));var results await Task.WhenAll(tasks); // 实际只调用了一次天气 API适用场景当缓存的数据生成成本较高如复杂计算、远程调用且需要防重复请求时LazyCache 是轻量级首选。—## 4. CacheManager分布式缓存与同步的解决方案CacheManager 是一个成熟的 .NET 缓存框架它支持多层缓存例如一级内存 二级 Redis并内置了缓存同步机制当某个节点更新缓存时通过 Redis Pub/Sub 通知其他节点失效。如果你的应用是分布式部署CacheManager 能帮你保持各节点缓存一致性。### 安装bashdotnet add package CacheManager.Coredotnet add package CacheManager.Redis### 代码示例多层缓存与同步csharpusing CacheManager.Core;// 1. 配置多层缓存内存 RedisRedis 作为后端并启用同步var config new ConfigurationBuilder() .WithDictionaryHandle(memory) // 一级内存缓存 .EnableStatistics() // 开启统计 .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(10)) .And .WithRedisHandle(redis, redisConnectionString) // 二级Redis 缓存 .EnableStatistics() .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromMinutes(30)) .And .WithRedisBackplane(redis) // 启用 Redis 背板同步事件 .Build();// 2. 创建缓存实例var cache CacheFactory.FromConfigurationobject(config);// 3. 使用缓存自动处理多级查找void UpdateUserCache(int userId, User user){ cache.Put($user:{userId}, user); // 同时写入内存和 Redis}User GetUserFromCache(int userId){ // 先从内存查找未命中则从 Redis 查找并回填到内存 var cached cache.Get($user:{userId}); return cached as User;}核心特性CacheManager 的Backplane机制确保当任意节点执行Put或Remove时其他节点的对应缓存会被自动清除从而避免“缓存不一致”问题。—## 5. MementoFX基于事件的缓存框架CQRS 友好MementoFX 是一个与事件溯源Event Sourcing和 CQRS 模式搭配的缓存库。它监听领域事件并自动更新或失效缓存。如果你的项目采用事件驱动架构MementoFX 可以让你告别手动清理缓存的繁琐工作。### 安装bashdotnet add package MementoFX.Persistence.MongoDBdotnet add package MementoFX.Caching.Redis### 代码示例事件驱动的缓存更新csharpusing MementoFX;using MementoFX.Caching;// 1. 定义领域事件public class UserNameChangedEvent : DomainEvent{ public Guid UserId { get; set; } public string NewName { get; set; }}// 2. 配置缓存与事件关联services.AddMementoFX(config { config.ConfigureCaching(cache { // 当 UserNameChangedEvent 发生时自动清除对应的用户缓存 cache.WhenUserNameChangedEvent(e $user:{e.UserId}); });});// 3. 业务代码自动触发缓存失效public class UserService{ private readonly IRepository _repository; private readonly ICacheManager _cache; public async Task ChangeUserNameAsync(Guid userId, string newName) { // 加载用户聚合根 var user await _repository.GetByIdUser(userId); user.ChangeName(newName); // 保存事件框架会自动发布 UserNameChangedEvent await _repository.Save(user); // 无需手动清理缓存MementoFX 监听到事件后自动失效 // 下次请求 GetUserAsync 时缓存未命中会重新加载 }}适用场景微服务架构中当缓存依赖于业务状态变化时MementoFX 能实现“声明式缓存管理”减少人为错误。—## 总结本文精选了 5 款 .NET 开源缓存框架它们各有侧重| 框架 | 核心特点 | 推荐场景 ||------|----------|----------||FusionCache| 混合缓存、防缓存击穿、软/硬过期 | 通用场景需要高可靠性和易用性 ||EasyCaching| 多后端支持、统一 API、批量操作 | 需要灵活切换缓存存储内存→Redis ||LazyCache| 轻量级、线程安全、懒加载 | 单体应用或简单缓存场景 ||CacheManager| 多层缓存、分布式同步 | 分布式系统需要缓存一致性 ||MementoFX| 事件驱动、CQRS 集成 | 事件溯源或 CQRS 架构项目 |选择缓存框架时建议从实际需求出发如果只是简单的内存缓存LazyCache 或 FusionCache 足够如果需要分布式支持EasyCaching 或 CacheManager 更合适而事件驱动架构则首选 MementoFX。最后无论选择哪个框架都要记住缓存不是银弹。合理设置过期时间、监控缓存命中率、处理缓存穿透和雪崩才是用好缓存的关键。希望这些框架能帮你写出更高效、更健壮的 .NET 应用