Microsoft 有 2 个解决方案 2 个不同的 NuGet 包用于缓存。两者都很棒。根据 Microsoft 的 建议 ,更喜欢使用, Microsoft.Extensions.Caching.Memory 因为它与 Asp.NET Core 集成得更好。它可以很 容易地注入 到 Asp .NET Core 的依赖注入机制中。
1、 Microsoft.Extensions.Caching.Memory
这是一个基本示例 Microsoft.Extensions.Caching.Memory :
public class SimpleMemoryCache { private MemoryCache _cache = new MemoryCache(new MemoryCacheOptions()); public TItem GetOrCreate(object key, Func createItem) { TItem cacheEntry; if (!_cache.TryGetValue(key, out cacheEntry))// Look for cache key. { // Key not in cache, so get data. cacheEntry = createItem(); // Save data in cache. _cache.Set(key, cacheEntry); } return cacheEntry; } }
用法:
var _avatarCache = new SimpleMemoryCache(); // ... var myAvatar = _avatarCache.GetOrCreate(userId, () => _database.GetAvatar(userId));
public class MemoryCacheWithPolicy { private MemoryCache _cache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 1024 }); public TItem GetOrCreate(object key, Func createItem) { TItem cacheEntry; if (!_cache.TryGetValue(key, out cacheEntry))// Look for cache key. { // Key not in cache, so get data. cacheEntry = createItem(); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSize(1)//Size amount //Priority on removing when reaching size limit (memory pressure) .SetPriority(CacheItemPriority.High) // Keep in cache for this time, reset time if accessed. .SetSlidingExpiration(TimeSpan.FromSeconds(2)) // Remove from cache after this time, regardless of sliding expiration .SetAbsoluteExpiration(TimeSpan.FromSeconds(10)); // Save data in cache. _cache.Set(key, cacheEntry, cacheEntryOptions); } return cacheEntry; } }
public class WaitToFinishMemoryCache { private MemoryCache _cache = new MemoryCache(new MemoryCacheOptions()); private ConcurrentDictionary _locks = new ConcurrentDictionary(); public async Task GetOrCreate(object key, Func> createItem) { TItem cacheEntry; if (!_cache.TryGetValue(key, out cacheEntry))// Look for cache key. { SemaphoreSlim mylock = _locks.GetOrAdd(key, k => new SemaphoreSlim(1, 1)); await mylock.WaitAsync(); try { if (!_cache.TryGetValue(key, out cacheEntry)) { // Key not in cache, so get data. cacheEntry = await createItem(); _cache.Set(key, cacheEntry); } } finally { mylock.Release(); } } return cacheEntry; } }
用法:
var _avatarCache = new WaitToFinishMemoryCache(); // ... var myAvatar = await _avatarCache.GetOrCreate(userId, async () => await _database.GetAvatar(userId));
4、代码说明
此实现锁定项目的创建。锁是特定于钥匙的。例如,如果我们正在等待获取 Alex 的 Avatar,我们仍然可以在另一个线程上获取 John 或 Sarah 的缓存值。