繁体   English   中英

ASP.NET Core 中的持久内存并发字典

[英]Persistent in-memory concurrent dictionary in ASP.NET Core

在 ASP.NET Core 应用程序中,我希望具有类似于以下内容的持久共享状态:

ConcurrentDictionary<string, Job> Jobs;

应用程序的各种组件将访问此共享状态(请求处理控制器、后台任务),但我主要关注的不是并发访问。 我很好奇是否有办法在我的 ASP.NET Core 应用程序的整个生命周期中保留这样的全局变量。

有没有地方可以定义这个全局Jobs变量,它不会被 ASP.NET Core 运行时破坏? 也许以某种方式利用MemoryCache

使用 Redis 之类的东西肯定会奏效,但我很好奇是否有针对 ASP.NET Core 中全局共享状态的健壮的内存/进程内解决方案。

您可以将ConcurrentDictionary包装在一个类中并将其注册为单例。

public class SharedJobs
{
    private readonly ConcurrentDictionary<string, Job> _jobs
        = new ConcurrentDictionary<string, Job>();

    public ConcurrentDictionary<string, Job> Jobs => _jobs;
}

在 Startup.cs 中

services.AddSingleton<SharedJobs>();

用法

public class Service
{
    private readonly SharedJobs _shared;

    public Service(SharedJobs shared) => _shared = shared;

    public void DoSomething()
    {
        var job = _shared.Jobs.GetOrAdd("Key", new Job("New Job when not found"));
    }
}

您可以进一步隐藏您在ConcurrentDictionary使用ConcurrentDictionary的事实,并仅向消费者公开所需的功能。

public class SharedJobs
{
    private readonly ConcurrentDictionary<string, Job> _jobs
        = new ConcurrentDictionary<string, Job>();

    public Job Get(string key)
    {
        return _jobs.GetOrAdd(key, CreateNewJob());
    }

    private Job CreateNewJob() {}
}

在您的控制器/服务的构造函数中请求一个IMemoryCache

首先添加到您的启动中以注册缓存服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

...在构造函数中要求它...

private IMemoryCache _cache;

public HomeController(IMemoryCache memoryCache)
{
    _cache = memoryCache;
}

......并使用它......

public IActionResult CacheTryGetValueSet()
{
    DateTime cacheEntry;

    // Look for cache key.
    if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
    {
        // Key not in cache, so get data.
        cacheEntry = DateTime.Now;

        // Set cache options.
        var cacheEntryOptions = new MemoryCacheEntryOptions()
            // Keep in cache for this time, reset time if accessed.
            .SetSlidingExpiration(TimeSpan.FromSeconds(3));

        // Save data in cache.
        _cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions);
    }

    return View("Cache", cacheEntry);
}

阅读 Microsoft 在 ASP.NET Core 中Cache in-memory了解更多详细信息。 以上所有代码都来自该页面。

此处提供的内存缓存是一个 Singleton - 缓存的单个实例将在应用程序的整个持续时间内存在。 但请注意,一旦进程关闭,一切都会被清除。


至于“如果我的缓存在我要求的那一刻没有价值怎么办?”

呃,欢迎使用多线程代码。 这只是生活的事实,缓存未命中是一回事。 因为整个周期都在内存中,所以它会“”“更多”“”可靠,但您仍然需要考虑它。

您可以使用AcroFS微型库在IMemoryCache之上使用持久层。 它将首先尝试从内存加载数据,然后尝试从磁盘加载。

如果您在不同位置有各种项目,您可以为缓存文件夹设置绝对路径。

// set cache
_memoryCache.Persistent().Set(key, jobs);

// get cache
var found = _memoryCache.Persistent().TryGetValue(cacheKey, out jobs);

// get or create
var jobs = await _memoryCache.Persistent().GetOrCreate(cacheKey, async entry => await loadJobsAsync());

暂无
暂无

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

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