这几乎是处理原子操作的经典案例。使用您的方法将项目添加到缓存涉及至少三个需要原子执行的操作:从 db 检索数据,将其存储在 dictionaryByKey 中,将其存储在 dictionaryByName 中。
ConcurrentDictionary 在这里对您没有帮助,因为该对象只能保护自己免受并发请求的影响——因为它不知道还有其他操作需要以原子方式发生,所以它无法帮助您避免一致性问题。
基本解决方案很简单:使用 rwlock 保护对缓存的读取和写入。ReaderWriterLock(Slim) 应该可以正常工作,特别是因为我假设大多数缓存命中都有望被读取。
假设 MyCache 是您的缓存类,获取项目将如下所示:
public class MyCache{
private ReaderWriterLock rwlock;
.....................
public object Get(int id)//same for the other one based on name
{
rwlock.AcquireReaderLock(Timeout.Infinite);
try{
if(cacheID.Contains(id)){return cacheID[id];}
//item MIGHT not be in cache (not certain since we're still under read lock)
//1. fetch from db BEFORE upgrade to write - avoid blocking all other readers
var item = GetItemFromStorage(id);//you get the idea
LockCookie lk = rwlock.UpgradeToWriterLock(Timeout.Infinite);
try{
if(cacheID.Contains(id)){return cacheID[id];}//check again!!!
//2. insert in cacheID
cacheID[id]=item;
//3. insert in cacheName
cacheName[item->key]=item;
//return value
return item;
}finally{rwlock.DowngradeFromWriterLock(ref lk);}
}
finally{rwlock.ExitReadLock();}
}