我有一个ASP.NET应用程序,该应用程序使用仅用于进行一次API调用的缓存。
此刻,如果我收到多个请求,它们最终都会命中API,而不是读取缓存,因为请求返回需要一段时间。如此有效地导致了我的缓存丢失,因此为了防止这种情况,我这样做了:
user_package
这可以通过在一个请求获得锁后立即阻止每个请求来进行工作,但是,就像互斥锁一样,它将允许一个接一个地访问缓存...
所以理想的行为是,每个请求都由select u.*,
p.name
from packages p
left join user_package u on u.pid = p.id
and u.uid=1
保留,然后第一个请求实际解决了API请求后,就让每个请求继续(因为它们都将进入缓存)。
我认为将class GetData
{
private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim( 1, 1 );
public async Task<ReferenceDataModel> GetReferenceDataAsync()
{
this.logger.Trace( "About to hit Reference Data lock" );
await SemaphoreSlim.WaitAsync( );
this.logger.Trace( "Acquired Thread" );
var referenceDataModel = await this.GetReferenceDataImplAsync();
this.logger.Trace( "Releasing Thread" );
SemaphoreSlim.Release( 1 );
return referenceDataModel;
}
private async Task<ReferenceDataModel> GetReferenceDataImplAsync()
{
if ( this.cache.Contains( ReferenceDataCacheKey ) )
{
this.logger.Trace( "Returning Cached Response" );
return (ReferenceDataModel) this.cache.Get( ReferenceDataCacheKey );
}
this.logger.Trace( "Making Reference Data API call" );
var response = await this.referenceDataProvider.GetReferenceDataAsync().ConfigureAwait( false );
this.AddReferenceDataToCache( response );
return response;
}
private void AddReferenceDataToCache(ReferenceDataModel mappedResponse)
{
var currentDateTime = DateTime.UtcNow;
var expirationOffset = currentDateTime.TimeOfDay < this.cacheExpiryTime
? currentDateTime.Date.Add(this.cacheExpiryTime)
: currentDateTime.AddDays(1).Date.Add(this.cacheExpiryTime);
this.cache.Set(ReferenceDataCacheKey, mappedResponse, expirationOffset);
this.logger.Trace( "Cached API Call Response" );
}
}
与WaitAsync()
一起使用可能会起作用,其想法是取消所有等待,以便所有线程继续运行。