.NET Runtime System.Runtime.Caching:高性能内存缓存完全指南
概述
System.Runtime.Caching命名空间提供了.NET应用程序中内存缓存的核心功能,是构建高性能、可扩展应用程序的关键组件。本文将深入探讨其架构设计、使用场景、最佳实践以及高级功能。
核心架构
缓存层次结构
默认能力集
MemoryCache提供以下核心能力:
| 能力类型 | 描述 | 枚举值 |
|---|---|---|
| 存储类型 | 内存提供程序 | InMemoryProvider |
| 监控能力 | 缓存条目变更监控 | CacheEntryChangeMonitors |
| 过期策略 | 绝对过期时间 | AbsoluteExpirations |
| 过期策略 | 滑动过期时间 | SlidingExpirations |
| 回调机制 | 移除回调 | CacheEntryRemovedCallback |
| 回调机制 | 更新回调 | CacheEntryUpdateCallback |
基础使用
初始化缓存实例
// 使用默认缓存实例
MemoryCache cache = MemoryCache.Default;
// 创建命名缓存实例
MemoryCache customCache = new MemoryCache("MyCustomCache");
// 带配置的缓存实例
NameValueCollection config = new NameValueCollection
{
{ "CacheMemoryLimitMegabytes", "100" },
{ "PhysicalMemoryLimitPercentage", "50" },
{ "PollingInterval", "00:05:00" }
};
MemoryCache configuredCache = new MemoryCache("ConfiguredCache", config);
基本CRUD操作
// 添加缓存项
cache.Add("user:123", userData, DateTimeOffset.Now.AddMinutes(30));
// 获取或添加(线程安全)
var data = cache.AddOrGetExisting("key", expensiveOperation(),
new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(10) });
// 获取缓存项
var cachedData = cache.Get("user:123");
// 更新缓存项
cache.Set("user:123", updatedUserData,
new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddHours(1) });
// 删除缓存项
cache.Remove("user:123");
高级功能
缓存策略配置
public class AdvancedCachePolicy
{
public static CacheItemPolicy CreateExpirationPolicy(TimeSpan slidingExpiration)
{
return new CacheItemPolicy
{
SlidingExpiration = slidingExpiration,
Priority = CacheItemPriority.Default
};
}
public static CacheItemPolicy CreateDependentPolicy(IEnumerable<string> filePaths)
{
var policy = new CacheItemPolicy();
foreach (var filePath in filePaths)
{
policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string> { filePath }));
}
return policy;
}
public static CacheItemPolicy CreateCallbackPolicy(
CacheEntryRemovedCallback removedCallback,
CacheEntryUpdateCallback updateCallback = null)
{
return new CacheItemPolicy
{
RemovedCallback = removedCallback,
UpdateCallback = updateCallback,
Priority = CacheItemPriority.NotRemovable
};
}
}
变更监控系统
// 创建缓存条目变更监控器
var keysToMonitor = new[] { "cacheKey1", "cacheKey2", "cacheKey3" };
CacheEntryChangeMonitor monitor = cache.CreateCacheEntryChangeMonitor(keysToMonitor);
// 监控文件变更
var fileMonitor = new HostFileChangeMonitor(new List<string> { "app.config", "settings.json" });
// 组合监控策略
var policy = new CacheItemPolicy();
policy.ChangeMonitors.Add(monitor);
policy.ChangeMonitors.Add(fileMonitor);
性能优化
内存管理配置
public class CacheMemoryManager
{
public static MemoryCache CreateOptimizedCache(string name, long memoryLimitMB, int physicalMemoryPercent)
{
var config = new NameValueCollection
{
{ "CacheMemoryLimitMegabytes", memoryLimitMB.ToString() },
{ "PhysicalMemoryLimitPercentage", physicalMemoryPercent.ToString() },
{ "PollingInterval", "00:02:00" } // 每2分钟检查一次内存使用
};
return new MemoryCache(name, config);
}
// 手动内存整理
public static long TrimCache(MemoryCache cache, int percentage)
{
return cache.Trim(Math.Clamp(percentage, 0, 100));
}
}
多线程安全模式
public class ThreadSafeCacheOperations
{
private readonly MemoryCache _cache;
private readonly object _lockObject = new object();
public ThreadSafeCacheOperations(MemoryCache cache)
{
_cache = cache;
}
public T GetOrAdd<T>(string key, Func<T> valueFactory, CacheItemPolicy policy)
{
var value = _cache.Get(key);
if (value != null)
{
return (T)value;
}
lock (_lockObject)
{
// 双重检查锁定模式
value = _cache.Get(key);
if (value != null)
{
return (T)value;
}
var newValue = valueFactory();
_cache.Add(key, newValue, policy);
return newValue;
}
}
}
实战场景
场景1:数据库查询结果缓存
public class DatabaseResultCache
{
private readonly MemoryCache _cache = MemoryCache.Default;
private readonly TimeSpan _defaultExpiration = TimeSpan.FromMinutes(15);
public T GetCachedQueryResult<T>(string queryKey, Func<T> queryExecutor)
{
var cachedResult = _cache.Get(queryKey);
if (cachedResult != null)
{
return (T)cachedResult;
}
var result = queryExecutor();
var policy = new CacheItemPolicy
{
SlidingExpiration = _defaultExpiration,
RemovedCallback = OnQueryResultRemoved
};
_cache.Add(queryKey, result, policy);
return result;
}
private void OnQueryResultRemoved(CacheEntryRemovedArguments arguments)
{
// 记录缓存移除原因,用于监控和分析
LogRemovalReason(arguments.RemovedReason);
}
}
场景2:API响应缓存
public class ApiResponseCache
{
private readonly MemoryCache _cache;
private readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new();
public ApiResponseCache()
{
_cache = new MemoryCache("ApiCache", new NameValueCollection
{
{ "CacheMemoryLimitMegabytes", "500" },
{ "PhysicalMemoryLimitPercentage", "70" }
});
}
public async Task<T> GetOrCreateAsync<T>(string cacheKey,
Func<Task<T>> factory, TimeSpan expiration)
{
if (_cache.Get(cacheKey) is T cachedValue)
{
return cachedValue;
}
var semaphore = _locks.GetOrAdd(cacheKey, _ => new SemaphoreSlim(1, 1));
await semaphore.WaitAsync();
try
{
// 双重检查
if (_cache.Get(cacheKey) is T recheckedValue)
{
return recheckedValue;
}
var value = await factory();
var policy = new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.Now.Add(expiration)
};
_cache.Add(cacheKey, value, policy);
return value;
}
finally
{
semaphore.Release();
_locks.TryRemove(cacheKey, out _);
}
}
}
监控和诊断
性能计数器集成
public class CacheMetrics
{
private readonly MemoryCache _cache;
public CacheMetrics(MemoryCache cache)
{
_cache = cache;
}
public CacheMetricsSnapshot GetSnapshot()
{
return new CacheMetricsSnapshot
{
TotalItems = _cache.GetCount(),
MemoryUsage = _cache.GetLastSize(),
MemoryLimit = _cache.CacheMemoryLimit,
PhysicalMemoryLimit = _cache.PhysicalMemoryLimit,
PollingInterval = _cache.PollingInterval
};
}
public void MonitorCacheHealth()
{
// 定期检查缓存健康状况
var snapshot = GetSnapshot();
var usagePercentage = (double)snapshot.MemoryUsage / snapshot.MemoryLimit * 100;
if (usagePercentage > 80)
{
// 触发内存整理
long itemsRemoved = _cache.Trim(20);
LogMemoryPressure(itemsRemoved, usagePercentage);
}
}
}
public class CacheMetricsSnapshot
{
public long TotalItems { get; set; }
public long MemoryUsage { get; set; }
public long MemoryLimit { get; set; }
public long PhysicalMemoryLimit { get; set; }
public TimeSpan PollingInterval { get; set; }
}
最佳实践
缓存键设计规范
| 模式 | 示例 | 优点 |
|---|---|---|
| 领域:ID | user:12345 | 清晰可读,易于管理 |
| 版本化键 | v2:product:list | 支持平滑升级 |
| 哈希键 | hash:{contentHash} | 内容寻址,避免重复 |
过期策略选择指南
内存限制配置建议
| 应用类型 | 内存限制 | 物理内存百分比 | 轮询间隔 |
|---|---|---|---|
| 小型应用 | 50-100MB | 20-30% | 2分钟 |
| 中型应用 | 100-500MB | 30-50% | 1分钟 |
| 大型应用 | 500MB-2GB | 50-70% | 30秒 |
故障排除
常见问题及解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 缓存项频繁失效 | 内存压力导致驱逐 | 增加内存限制或优化缓存策略 |
| 性能计数器异常 | 平台不支持 | 检查操作系统兼容性 |
| 回调函数不执行 | 策略配置错误 | 验证RemovedCallback和UpdateCallback配置 |
| 内存泄漏 | 未释放ChangeMonitor | 确保正确实现IDisposable |
调试和日志记录
public class CacheDebugger
{
public static void EnableDebugLogging(MemoryCache cache)
{
// 示例:添加全局移除回调进行日志记录
// 注意:实际应用中需要更复杂的日志记录策略
}
public static void DumpCacheContents(MemoryCache cache)
{
foreach (var item in cache)
{
Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");
}
}
}
总结
System.Runtime.Caching提供了强大而灵活的内存缓存解决方案,通过合理的配置和使用,可以显著提升应用程序性能和可扩展性。关键要点包括:
- 合理配置内存限制:根据应用需求调整CacheMemoryLimit和PhysicalMemoryLimit
- 选择适当的过期策略:根据数据特性选择绝对过期或滑动过期
- 实现监控和回调:利用ChangeMonitor和回调函数实现高级缓存逻辑
- 线程安全设计:在多线程环境中确保缓存操作的原子性
- 性能监控:定期检查缓存使用情况,优化内存使用
通过掌握这些核心概念和最佳实践,您可以构建出高效、可靠的缓存系统,为您的.NET应用程序提供卓越的性能表现。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



