MVC Web アプリケーションのキャッシング マネージャーに取り組んでいます。このアプリには、構築にコストがかかる非常に大きなオブジェクトがいくつかあります。アプリケーションの有効期間中に、ユーザーの要求に基づいて、これらのオブジェクトをいくつか作成する必要がある場合があります。ビルドすると、ユーザーはオブジェクト内のデータを操作するため、多くの読み取りアクションが発生します。場合によっては、キャッシュされたオブジェクトのいくつかのマイナー データ ポイントを更新する必要があります (作成と置換には時間がかかりすぎます)。
以下は、これを支援するために作成したキャッシュ マネージャー クラスです。基本的なスレッド セーフを超えて、私の目標は次のとおりでした。
- オブジェクトに対する複数の読み取りを許可しますが、更新要求時にそのオブジェクトへのすべての読み取りをロックします
- オブジェクトがまだ存在しない場合は、オブジェクトが一度だけ作成されるようにします (長いビルド アクションであることに注意してください)。
キャッシュが多くのオブジェクトを格納できるようにし、(すべてのオブジェクトに対して 1 つのロックではなく) オブジェクトごとにロックを維持します。
public class CacheManager { private static readonly ObjectCache Cache = MemoryCache.Default; private static readonly ConcurrentDictionary<string, ReaderWriterLockSlim> Locks = new ConcurrentDictionary<string, ReaderWriterLockSlim>(); private const int CacheLengthInHours = 1; public object AddOrGetExisting(string key, Func<object> factoryMethod) { Locks.GetOrAdd(key, new ReaderWriterLockSlim()); var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddHours(CacheLengthInHours) }; return Cache.AddOrGetExisting (key, new Lazy<object>(factoryMethod), policy); } public object Get(string key) { var targetLock = AcquireLockObject(key); if (targetLock != null) { targetLock.EnterReadLock(); try { var cacheItem = Cache.GetCacheItem(key); if(cacheItem!= null) return cacheItem.Value; } finally { targetLock.ExitReadLock(); } } return null; } public void Update<T>(string key, Func<T, object> updateMethod) { var targetLock = AcquireLockObject(key); var targetItem = (Lazy<object>) Get(key); if (targetLock == null || key == null) return; targetLock.EnterWriteLock(); try { updateMethod((T)targetItem.Value); } finally { targetLock.ExitWriteLock(); } } private ReaderWriterLockSlim AcquireLockObject(string key) { return Locks.ContainsKey(key) ? Locks[key] : null; } }
スレッドセーフを維持しながら目標を達成できていますか? 私の目標を達成するためのより良い方法はありますか?
ありがとう!
更新: つまり、ここでの結論は、1 つの領域で本当に多くのことをしようとしていたということです。何らかの理由で、キャッシュを管理するのと同じクラスで Get / Update 操作を管理するのは良い考えだと確信しました。Groo のソリューションを見て問題を再考した後、かなりの量のリファクタリングを行うことができ、直面していたこの問題を取り除くことができました。