You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中实现简单内存缓存是否有标准方案?

一、缓存Count为0的问题排查

你的核心问题大概率是初始化缓存的代码存在执行异常或服务获取错误,导致缓存未被正确设置,具体排查点如下:

  1. 服务获取方式错误
    初始化缓存时,在using (var scope = _serviceProvider.CreateScope())代码块内,应该使用scope.ServiceProvider获取Scoped生命周期的服务(比如IRepository),而非直接用根容器的_serviceProvider。同时建议用GetRequiredService<T>替代GetService<T>,这样获取不到服务时会直接抛出异常,便于快速定位问题:
    public Task StartAsync(CancellationToken cancellationToken)
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var repo = scope.ServiceProvider.GetRequiredService<IRepository>();
            var values = repo.GetValues();
    
            var cache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
            cache.Set("ValuesList", values);
        }
        return Task.CompletedTask;
    }
    
  2. 缓存键不匹配
    检查调用接口时传入的key是否确实是"ValuesList",如果传入其他值,自然无法命中缓存,_cache.Count也会显示0。
  3. 初始化代码未执行/存在静默异常
    在StartAsync中添加日志输出,确认代码是否执行、是否获取到数据、缓存是否设置成功:
    // 先注入ILogger
    private readonly ILogger<InitializeCacheService> _logger;
    public InitializeCacheService(IServiceProvider serviceProvider, ILogger<InitializeCacheService> logger)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
    }
    
    public Task StartAsync(CancellationToken cancellationToken)
    {
        try
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var repo = scope.ServiceProvider.GetRequiredService<IRepository>();
                var values = repo.GetValues();
                _logger.LogInformation("获取到参考表数据:{Count}条", values?.Count ?? 0);
    
                var cache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
                cache.Set("ValuesList", values);
                _logger.LogInformation("缓存设置完成,当前缓存项数量:{Count}", cache.Count);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "初始化缓存失败");
        }
        return Task.CompletedTask;
    }
    
  4. 控制器缓存注入验证
    确认控制器中的_cache是通过构造函数注入的IMemoryCache,而非自行实例化:
    private readonly IMemoryCache _cache;
    public YourController(IMemoryCache cache)
    {
        _cache = cache;
    }
    

二、实现方式是否符合标准

你的思路是合理的,用IHostedService预加载静态参考表到内存缓存,适合这类不修改的场景,但可以做以下优化让实现更规范:

  1. 改用BackgroundService
    继承BackgroundService(IHostedService的抽象实现)比直接实现IHostedService更规范,它自带异步处理框架,适合一次性初始化场景:
    public class InitializeCacheService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<InitializeCacheService> _logger;
    
        public InitializeCacheService(IServiceProvider serviceProvider, ILogger<InitializeCacheService> logger)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
        }
    
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // 初始化缓存逻辑同前
        }
    }
    
  2. 添加缓存策略
    虽然数据是静态的,但可以设置缓存优先级和过期时间,避免内存不足时被意外清理,或未来数据更新时能自动刷新:
    cache.Set("ValuesList", values, new MemoryCacheEntryOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(30),
        Priority = CacheItemPriority.NeverRemove
    });
    
  3. 考虑多实例场景
    如果应用是多实例部署,每个实例会独立加载缓存,这在静态数据场景下没问题,但如果未来数据需要更新,需考虑所有实例同步刷新的方案(比如分布式缓存)。

三、纯内存存储的安全风险

纯内存缓存的风险针对你的场景极低,主要集中在以下几点:

  • 应用重启丢失数据:内存缓存是进程内存储,应用重启后缓存会清空,但你的场景会在启动时自动重新加载,仅会多一次数据库查询,无业务影响。
  • 敏感数据泄露:如果缓存的是敏感数据,进程内存可能被恶意dump获取,但你的场景是静态参考表,一般为非敏感数据,风险可忽略;若确实涉及敏感数据,建议加密后再存入缓存。
  • 内存泄漏:静态数据数量固定,只要初始化时加载一次,不会出现内存持续增长的问题;但若未来扩展缓存逻辑,需注意设置过期策略避免泄漏。
  • 多实例一致性问题:多实例部署时,若数据意外修改,不同实例的缓存会不一致,但你明确数据不会修改,此风险不存在。

内容的提问来源于stack exchange,提问作者choopau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:07:17