引言:为什么高级缓存能改变一切
在现代高并发架构中,响应速度和降低数据库负载是关键任务。C# (.NET) 中的缓存已不再是简单的结果存储:它是一套复杂的状态管理、生命周期和数据一致性系统。在高级层面,开发者必须根据场景在 Redis、Memcached 和内置解决方案之间做出选择。
本文将深入探讨 .NET 生态系统中的三种主要缓存方法,比较它们的性能、实施复杂度以及常见错误。您将学习如何配置基于 Redis 的分布式缓存、优化 Memcached 以应对高负载,以及何时内置的 IMemoryCache 是最佳选择。
.NET 内置缓存:IMemoryCache 和 IDistributedCache
IMemoryCache — 快速本地缓存
内置缓存 IMemoryCache 来自 Microsoft.Extensions.Caching.Memory 命名空间,是单实例应用程序的理想解决方案。它将数据存储在进程内存中,提供最低延迟。
// 在 Startup.cs 或 Program.cs 中注册builder.Services.AddMemoryCache();
// 在服务中使用public class ProductService{ private readonly IMemoryCache _cache;
public ProductService(IMemoryCache cache) { _cache = cache; }
public async Task<Product> GetProductAsync(int id) { string cacheKey = $"product_{id}"; if (!_cache.TryGetValue(cacheKey, out Product product)) { product = await _repository.GetProductByIdAsync(id); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)) .SetSlidingExpiration(TimeSpan.FromMinutes(1)) .SetPriority(CacheItemPriority.High);
_cache.Set(cacheKey, product, cacheEntryOptions); } return product; }}优点:零网络延迟、配置简单、支持滑动和绝对过期。
缺点:无法在多个服务器间扩展;受限于进程 RAM 容量。
IDistributedCache — 分布式缓存的抽象层
IDistributedCache 接口允许在不更改业务逻辑的情况下轻松切换 Redis、SQL Server 或 NCache。默认实现是 MemoryDistributedCache(本地),但生产环境通常选择 Redis。
// 注册 Redis 实现builder.Services.AddStackExchangeRedisCache(options =>{ options.Configuration = "localhost:6379"; options.InstanceName = "SampleInstance";});
// 使用public async Task SetCacheAsync(string key, byte[] data){ var cache = context.RequestServices.GetRequiredService<IDistributedCache>(); await cache.SetAsync(key, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) });}关键优势在于统一性:您只需编写一次代码,缓存提供程序可通过配置进行切换。
C# 中的 Redis:高级技术与模式
连接与连接池
在 .NET 中操作 Redis 使用 StackExchange.Redis 库。不要每次都创建新连接,而是使用多路复用——整个应用程序共享一个连接。
// 全局单例public static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false");
// 获取数据库IDatabase db = redis.GetDatabase(0);
// 基本操作await db.StringSetAsync("user:1", "John Doe", TimeSpan.FromMinutes(30));string name = await db.StringGetAsync("user:1");
博客
书籍推荐
推荐阅读