简体   繁体   English

如何清除 ASP.NET Core 中的 MemoryCache?

[英]How to clear MemoryCache in ASP.NET Core?

How to correctly clear IMemoryCache from ASP.NET Core?如何从 ASP.NET Core 正确清除 IMemoryCache?

I believe this class is missing Clear method, but anyway how to deal with it?我相信这个类缺少 Clear 方法,但无论如何如何处理它? In my project I'm caching DocumentRepository's methods for 24 hours where I'm getting lots of rows from database.在我的项目中,我将 DocumentRepository 的方法缓存了 24 小时,我从数据库中获取了很多行。 But sometimes I can change the database, so I want to clear the IMemoryCache as it has got rubbish data.但有时我可以更改数据库,所以我想清除 IMemoryCache,因为它有垃圾数据。

IMemoryCache indeed lacks a Clear() method, but it's not hard to implement one yourself. 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();
        }
    }

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

There is an easy way to clear it that may not work in all environments, but where it does work, it works well.有一种简单的方法可以清除它,该方法可能不适用于所有环境,但在它有效的地方,它运行良好。

If you're getting your IMemoryCache object through dependency injection, there is a good chance you'll actually be receiving a MemoryCache object.如果您通过依赖注入获取IMemoryCache对象,则很有可能您实际上会收到一个MemoryCache对象。 MemoryCache does have a method called Compact() that will clear the cache. MemoryCache确实有一个名为Compact()的方法可以清除缓存。 You can try to cast the object to MemoryCache and, if successful, call Compact .您可以尝试将对象MemoryCacheMemoryCache ,如果成功,则调用Compact

Example:例子:

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.";
 }

The cache class and interface don't have any methods for clearing neither ones to iterate over the keys, since it's not meant to be a list and in ASP.NET Core applications one usually use IDistributedCache interface as dependency, since it easier allows you to later change from a local memory cache to a distributed cache (such as memd or Redis).缓存类和接口没有任何方法可以清除它们来迭代键,因为它不是一个列表,并且在 ASP.NET Core 应用程序中,通常使用IDistributedCache接口作为依赖项,因为它更容易让您稍后从本地内存缓存更改为分布式缓存(例如 memd 或 Redis)。

Instead, if you want to invalidate a specific row, you should remove the cached entry via cache.Remove(myKey) .相反,如果您想让特定行无效,您应该通过cache.Remove(myKey)删除缓存的条目。

Of course, this requires you to know the key you want to invalidate.当然,这需要您知道要使之无效的密钥。 Typically you do that via events.通常你通过事件来做到这一点。 Every time you update an entry in the database, you would fire up an event.每次更新数据库中的条目时,都会触发一个事件。 This event will be caught by a background service and cause a cache invalidation.此事件将被后台服务捕获并导致缓存失效。

Locally this can be done with any pub/sub library.在本地,这可以通过任何发布/订阅库来完成。 In distributed scenarios you may want to use pub/sub features of the distributed cache (ie Redis).在分布式场景中,您可能希望使用分布式缓存(即 Redis)的发布/订阅功能。

In cases of lookup tables (where many values are affected), you can have a service refresh the cache (ie every 5 to 10 minutes via a background task using a scheduling library such as hangfire or quart.net).在查找表的情况下(其中许多值受到影响),您可以让服务刷新缓存(即,通过使用诸如hangfire 或 quart.net 之类的调度库的后台任务每 5 到 10 分钟刷新一次)。

Home work Questions家庭作业问题

But one question you should ask yourself: Is it really a good idea to cache documents for 24 hours if they change frequently?但是您应该问自己一个问题:如果文档经常更改,将其缓存 24 小时真的是个好主意吗?

Does the loading of a single document takes so much time, that caching it 24 hours will be worth?加载单个文档是否需要花费这么多时间,缓存 24 小时值得吗? Or are shorter times good enough (15, 30, 60 minutes)?还是较短的时间就足够了(15、30、60 分钟)?

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

memoryCache.Remove("your_key");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM