【问题标题】:How to clear MemoryCache in ASP.NET Core?如何清除 ASP.NET Core 中的 MemoryCache?
【发布时间】:2019-05-26 17:38:31
【问题描述】:

如何正确清除 ASP.NET Core 中的 IMemoryCache?

我相信这个类缺少 Clear 方法,但无论如何如何处理呢?在我的项目中,我将 DocumentRepository 的方法缓存 24 小时,从数据库中获取大量行。但有时我可以更改数据库,所以我想清除 IMemoryCache,因为它有垃圾数据。

【问题讨论】:

标签: c# asp.net caching asp.net-core memorycache


【解决方案1】:

IMemoryCache 确实缺少Clear() 方法,但是自己实现一个并不难。

    public class CacheWrapper
    {
        private readonly IMemoryCache _memoryCache;
        private CancellationTokenSource _resetCacheToken = new();

        public CacheWrapper(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public void Add(object key, object value, MemoryCacheEntryOptions memoryCacheEntryOptions)
        {
            using var entry = _memoryCache.CreateEntry(key);
            entry.SetOptions(memoryCacheEntryOptions);
            entry.Value = value;

            // add an expiration token that allows us to clear the entire cache with a single method call
            entry.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
        }

        public void Clear()
        {
            _resetCacheToken.Cancel(); // this triggers the CancellationChangeToken to expire every item from cache

            _resetCacheToken.Dispose(); // dispose the current cancellation token source and create a new one
            _resetCacheToken = new CancellationTokenSource();
        }
    }

基于https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1#cache-dependencieshttps://stackoverflow.com/a/45543023/2078975

【讨论】:

    【解决方案2】:

    有一种简单的方法可以清除它,它可能不适用于所有环境,但在它有效的地方,它工作得很好。

    如果您通过依赖注入获取IMemoryCache 对象,则很有可能您实际上会收到MemoryCache 对象。 MemoryCache 确实 有一个名为Compact() 的方法可以清除缓存。您可以尝试将对象转换为MemoryCache,如果成功,则调用Compact

    例子:

    string message;
    // _memoryCache is of type IMemoryCache and was set via dependency injection.
    var    memoryCache = _memoryCache as MemoryCache;
    if (memoryCache != null)
    {
        memoryCache.Compact(1);
     
        message ="Cache cleared";
     } else {
        message = "Could not cast cache object to MemoryCache. Cache NOT cleared.";
     }
    

    【讨论】:

      【解决方案3】:

      缓存类和接口没有任何方法可以清除任何一个来迭代键,因为它不是一个列表,并且在 ASP.NET Core 应用程序中通常使用IDistributedCache 接口作为依赖项,因为它更容易让您以后从本地内存缓存更改为分布式缓存(例如 memd 或 Redis)。

      相反,如果您想使特定行无效,您应该通过cache.Remove(myKey) 删除缓存条目。

      当然,这需要您知道要失效的密钥。通常,您通过事件来做到这一点。每次更新数据库中的条目时,都会触发一个事件。此事件将被后台服务捕获并导致缓存失效。

      这可以在本地使用任何 pub/sub 库来完成。在分布式场景中,您可能希望使用分布式缓存(即 Redis)的发布/订阅功能。

      在查找表的情况下(许多值受到影响),您可以让服务刷新缓存(即,通过使用 hangfire 或 quart.net 等调度库的后台任务每 5 到 10 分钟刷新一次)。

      家庭作业问题

      但是您应该问自己一个问题:如果文档频繁更改,将其缓存 24 小时真的是个好主意吗?

      加载单个文档需要这么多时间,是否值得将其缓存 24 小时?还是更短的时间(15、30、60 分钟)就足够了?

      【讨论】:

      • 它并没有经常改变。它甚至可以每月或两个月更改一次,但有一天它可以更改,所以我必须清除缓存,因为它不会是最新的
      • 好吧,就像我说的,不知道您在缓存未命中时获取文档需要多长时间(如果它小于 10 毫秒并且该文档在缓存时间内被读取了几次) ,缓存时间低至 5、10 或 15 分钟是完全可以接受的)。如果您的文件需要很长时间才能获得,我会在那里查看。如果额外的基础设施([分布式]发布/订阅)超出了您的范围
      【解决方案4】:

      要清除内存缓存,只需按键删除内存缓存,如下所示:

      memoryCache.Remove("your_key");

      【讨论】:

      • 这将删除 your_key 而不是按照要求清除 your_cache
      • 根据要求“我想清除 IMemoryCache,因为它有垃圾数据。”我相信 Remove() 方法是最好的选择。
      猜你喜欢
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多