如何实现数据大小限制的缓存?
How to implement Caching with data size limit?
我有多个线程请求必须通过网络加载的数据。
为了减少网络流量和加快响应速度,我想缓存经常被请求的数据。我也想限制缓存的数据大小。
我的 class 看起来像这样:
public class DataProvider
{
private ConcurrentDictionary<string, byte[]> dataCache;
private int dataCacheSize;
private int maxDataCacheSize;
private object dataCacheSizeLockObj = new object();
public DataProvider(int maxCacheSize)
{
maxDataCacheSize = maxCacheSize;
dataCache = new ConcurrentDictionary<string,byte[]>();
}
public byte[] GetData(string key)
{
byte[] retVal;
if (dataCache.ContainsKey(key))
{
retVal = dataCache[key];
}
else
{
retVal = ... // get data from somewhere else
if (dataCacheSize + retVal.Length <= maxDataCacheSize)
{
lock (dataCacheSizeLockObj)
{
dataCacheSize += retVal.Length;
}
dataCache[key] = retVal;
}
}
return retVal;
}
}
我的问题是:如何确保 dataCacheSize
始终具有正确的值?如果两个线程同时请求相同的未缓存数据,它们都会将自己的数据写入缓存,这没有问题,因为数据相同,第二个线程只会用相同的数据覆盖缓存数据。但是我怎么知道它是否被覆盖以避免计算它的大小两次?
也可能发生,两个线程同时添加数据导致 dataCache 大小大于允许的...
有没有一种无需添加复杂锁定机制即可完成此任务的优雅方法?
由于您在锁内更新 dataCacheSize
,您可以在这里检查它是否保持正确:
if (dataCacheSize + retVal.Length <= maxDataCacheSize)
{
lock (dataCacheSizeLockObj)
{
if (dataCacheSize + retVal.Length > maxDataCacheSize)
{
return retVal;
}
dataCacheSize += retVal.Length;
}
byte[] oldVal = dataCache.GetOrAdd(key, retVal);
if (oldVal != retVal)
{
// retVal wasn't actually added
lock (dataCacheSizeLockObj)
{
dataCacheSize -= retVal.Length;
}
}
}
与其尝试 "roll you own" 缓存,不如看看 System.Runtime.Caching.MemoryCache。见上面的评论。
我有多个线程请求必须通过网络加载的数据。 为了减少网络流量和加快响应速度,我想缓存经常被请求的数据。我也想限制缓存的数据大小。
我的 class 看起来像这样:
public class DataProvider
{
private ConcurrentDictionary<string, byte[]> dataCache;
private int dataCacheSize;
private int maxDataCacheSize;
private object dataCacheSizeLockObj = new object();
public DataProvider(int maxCacheSize)
{
maxDataCacheSize = maxCacheSize;
dataCache = new ConcurrentDictionary<string,byte[]>();
}
public byte[] GetData(string key)
{
byte[] retVal;
if (dataCache.ContainsKey(key))
{
retVal = dataCache[key];
}
else
{
retVal = ... // get data from somewhere else
if (dataCacheSize + retVal.Length <= maxDataCacheSize)
{
lock (dataCacheSizeLockObj)
{
dataCacheSize += retVal.Length;
}
dataCache[key] = retVal;
}
}
return retVal;
}
}
我的问题是:如何确保 dataCacheSize
始终具有正确的值?如果两个线程同时请求相同的未缓存数据,它们都会将自己的数据写入缓存,这没有问题,因为数据相同,第二个线程只会用相同的数据覆盖缓存数据。但是我怎么知道它是否被覆盖以避免计算它的大小两次?
也可能发生,两个线程同时添加数据导致 dataCache 大小大于允许的...
有没有一种无需添加复杂锁定机制即可完成此任务的优雅方法?
由于您在锁内更新 dataCacheSize
,您可以在这里检查它是否保持正确:
if (dataCacheSize + retVal.Length <= maxDataCacheSize)
{
lock (dataCacheSizeLockObj)
{
if (dataCacheSize + retVal.Length > maxDataCacheSize)
{
return retVal;
}
dataCacheSize += retVal.Length;
}
byte[] oldVal = dataCache.GetOrAdd(key, retVal);
if (oldVal != retVal)
{
// retVal wasn't actually added
lock (dataCacheSizeLockObj)
{
dataCacheSize -= retVal.Length;
}
}
}
与其尝试 "roll you own" 缓存,不如看看 System.Runtime.Caching.MemoryCache。见上面的评论。