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