【发布时间】:2020-08-10 15:01:06
【问题描述】:
我们即将使用 ASP.NET Core 的内置内存缓存解决方案来缓存外部系统响应。 (稍后我们可能会从内存转移到IDistributedCache。)
我们想使用Mircosoft.Extensions.Caching.Memory 的IMemoryCache 作为MSDN suggests。
我们需要限制缓存的大小,因为默认情况下它是无限的。
因此,在将其集成到我们的项目之前,我创建了以下 POC 应用程序来使用它。
我的自定义 MemoryCache 以指定大小限制
public interface IThrottledCache
{
IMemoryCache Cache { get; }
}
public class ThrottledCache: IThrottledCache
{
private readonly MemoryCache cache;
public ThrottledCache()
{
cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = 2
});
}
public IMemoryCache Cache => cache;
}
将此实现注册为单例
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IThrottledCache>(new ThrottledCache());
}
我创建了一个非常简单的控制器来使用这个缓存。
玩 MemoryCache 的沙盒控制器
[Route("api/[controller]")]
[ApiController]
public class MemoryController : ControllerBase
{
private readonly IMemoryCache cache;
public MemoryController(IThrottledCache cacheSource)
{
this.cache = cacheSource.Cache;
}
[HttpGet("{id}")]
public IActionResult Get(string id)
{
if (cache.TryGetValue(id, out var cachedEntry))
{
return Ok(cachedEntry);
}
else
{
var options = new MemoryCacheEntryOptions { Size = 1, SlidingExpiration = TimeSpan.FromMinutes(1) };
cache.Set(id, $"{id} - cached", options);
return Ok(id);
}
}
}
如您所见,我的/api/memory/{id} 端点可以在两种模式下工作:
- 从缓存中检索数据
- 将数据存储到缓存中
我观察到以下奇怪的行为:
- 获取
/api/memory/first
1.1) 返回first
1.2) 缓存条目:first - 获取
/api/memory/first
2.1) 返回first - cached
2.2) 缓存条目:first - 获取
/api/memory/second
3.1) 返回second
3.2) 缓存条目:first、second - 获取
/api/memory/second
4.1) 返回second - cached
4.2) 缓存条目:first、second - 获取
/api/memory/third
5.1) 返回third
5.2)缓存条目:first,second - 获取
/api/memory/third
6.1) 返回third
6.2) 缓存条目:second、third - 获取
/api/memory/third
7.1) 返回third - cached
7.2) 缓存条目:second、third
正如您在第 5 个端点调用中看到的那样,我达到了极限。所以我的期望如下:
- 缓存逐出策略会删除
first最旧的条目 - 缓存将
third存储为最新的
但这种期望的行为只发生在第 6 次调用时。
那么,我的问题是,当达到大小限制时,为什么我必须调用两次Set 才能将新数据放入 MemoryCache?
编辑:同时添加计时相关信息
在测试整个请求流/链期间大约需要 15 秒甚至更少。
即使我将 SlidingExpiration 更改为 1 小时,行为仍然完全相同。
【问题讨论】:
-
第三个不会添加到缓存中,缓存已满,有“第一”和“第二”。将“第一个”条目添加到缓存后一分钟后,它会过期并且可以添加新项目。至少,我猜它是这样工作的,去寻找文档......
-
是的,请参阅副本:“如果缓存条目大小的总和超过 SizeLimit 指定的值,则不会缓存条目”。所以这不是您需要的第二次通话,而是两次通话之间的时间。
-
@CodeCaster 整个请求流大约需要 15 秒。如果我将
SlidingExpiration更改为 1 小时,它的行为方式完全相同。 -
我已经相应地更新了。
-
如何观察缓存的条目?
标签: c# asp.net-core asp.net-core-3.1 memorycache