.net 从ConcurrentDictionary中消失的条目

.net 从ConcurrentDictionary中消失的条目,.net,caching,singleton,concurrentdictionary,.net,Caching,Singleton,Concurrentdictionary,我托管了一个跟踪帐户权限的API。权限存储在API数据库中。为了能够在数据库速度非常慢或不可用时准确响应,我选择尝试在内存中反映数据库权限 为此,我选择了ConcurrentDictionary。密钥是一个帐户id,值是它的权限。这被包装在MemoryStorageService中的服务中,该服务在我们的DI框架中注册为单例 为了能够在内存中反映数据库,采取以下步骤: 在应用程序启动时,整个数据库表被预加载到内存中(大约100k个条目) 对帐户权限进行更改时,会在数据库和内存存储中更新这些权限

我托管了一个跟踪帐户权限的API。权限存储在API数据库中。为了能够在数据库速度非常慢或不可用时准确响应,我选择尝试在内存中反映数据库权限

为此,我选择了
ConcurrentDictionary
。密钥是一个帐户id,值是它的权限。这被包装在MemoryStorageService中的服务
中,该服务在我们的DI框架中注册为单例

为了能够在内存中反映数据库,采取以下步骤:

  • 在应用程序启动时,整个数据库表被预加载到内存中(大约100k个条目)
  • 对帐户权限进行更改时,会在数据库和内存存储中更新这些权限
  • 我的问题是,对于api调用的几个百分比,内存中的权限无法找到,而它们存在于数据库中。我添加了日志记录,因此我知道特定帐户的权限是在启动时从数据库加载的。在API启动之后,这种情况经常发生。所以事件的顺序是这样的:

  • Api启动
  • 帐户(123、144、168)的权限加载到ConcurrentDictionary中
  • 帐户144尝试获取其权限
  • 在内存中找不到帐户144的权限但在数据库中存在的日志项
  • 有什么建议吗

    public class InMemoryStorageService : IInMemoryStorageService
    {
        private readonly ILogFactory _logFactory;
        private readonly IPermissionRepository _permissionRepository;
        private readonly ConcurrentDictionary<string, Permission> _inMemoryStore;
    
        private ILog _log;
        protected ILog Log => _log ?? (_log = _logFactory.GetLogger(GetType()));
    
        public InMemoryStorageService(ILogFactory logFactory, IPermissionRepository permissionRepository)
        {
            _logFactory = logFactory;
            _permissionRepository = permissionRepository;
            _inMemoryStore = new ConcurrentDictionary<string, Permission>();
        }
    
        public Permission GetPermission(string accountId)
        {
            Permission value;
            if (_inMemoryStore.TryGetValue(accountId, out value)) return value;
    
            return null;
        }
    
        public void AddOrUpdatePermission(Permission permissions)
        {
            if (permissions == null) throw new ArgumentNullException(nameof(permissions));
    
            _inMemoryStore.AddOrUpdate(permissions.AccountId, permissions,
                (accId, currentPermissions) =>
                    permissions.Updated > currentPermissions?.Updated ? permissions : currentPermissions);
        }
    
        public void PreloadStorageFromDb()
        {
            try
            {
                var stopWatch = new Stopwatch();
                stopWatch.Start();
    
                int addedPermissions = 0;
                var permissions = _permissionRepository.GetAll();
                foreach (var accountPermission in permissions)
                {
                    AddOrUpdatePermission(accountPermission);
                    addedPermissions++;
                }
    
                stopWatch.Stop();
                Log.InfoAsJson($"{nameof(PreloadStorageFromDb)}", new
                {
                    addedPermissions,
                    timeToLoadCacheInMilliseconds = stopWatch.ElapsedMilliseconds
                });
            }
            catch (Exception e)
            {
                Log.ErrorAsJson($"{nameof(PreloadStorageFromDb)}", null, e);
            }
        }
    }
    
    MemoryStorageService中的公共类:IInMemoryStorageService
    {
    私人只读ILogFactory\u logFactory;
    专用只读IPermissionRepository\u permissionRepository;
    MemoryStore中的私有只读ConcurrentDictionary;
    私人ILog_日志;
    受保护的ILog日志=>\u日志??(\u日志=\u logFactory.GetLogger(GetType());
    公共InMemoryStorageService(ILogFactory logFactory、IPermissionRepository permissionRepository)
    {
    _logFactory=logFactory;
    _permissionRepository=permissionRepository;
    _inMemoryStore=新的ConcurrentDictionary();
    }
    公共权限GetPermission(字符串accountId)
    {
    权限值;
    if(_inMemoryStore.TryGetValue(accountId,out value))返回值;
    返回null;
    }
    public void AddOrUpdatePermission(权限)
    {
    如果(permissions==null)抛出新的ArgumentNullException(nameof(permissions));
    _inMemoryStore.AddOrUpdate(permissions.AccountId、permissions、,
    (accId,currentPermissions)=>
    权限.Updated>currentPermissions?.Updated?权限:currentPermissions);
    }
    public-void-storagefromdb()
    {
    尝试
    {
    var stopWatch=新秒表();
    秒表。开始();
    int addedPermissions=0;
    var permissions=_permissionRepository.GetAll();
    foreach(权限中的var accountPermission)
    {
    AddOrUpdatePermission(accountPermission);
    添加权限++;
    }
    秒表;
    Log.InfoAsJson($“{nameof(preload-storagefromdb)}”,新增
    {
    新增权限,
    TimeToLoadCachein毫秒=秒表。延时毫秒
    });
    }
    捕获(例外e)
    {
    Log.ErrorAsJson($“{nameof(preload-storagefromdb)}”,null,e);
    }
    }
    }
    
    DI框架是SimpleInjector

    container.RegisterInstance<IInMemoryStorageService>(new InMemoryStorageService(logFactory, new PermissionRepository(appSettings, logFactory)));
    
    container.RegisterInstance(新的InMemoryStorageService(logFactory,新的PermissionRepository(appSettings,logFactory));
    

    该api通过Owin自托管。它是通过.NET Framework 4.7.1 Windows服务启动的。

    无需担心。我很愚蠢。我假设记录的条目来自api。但是它们来自于引擎,它不预加载内存存储

    抱歉