background
Cache breakdown refers to data that is not in the cache but is present in the database (usually the cache time expires). At this time, because there are a lot of concurrent users, and the data is not read by the cache, and the data is also retrieved from the database at the same time, the database pressure increases instantly, causing excessive pressure.
Solution
1. Set the hotspot data to never expire.
2. Add a mutex lock, and the reference code for the mutex lock is as follows:
2.1. Generate object() according to key
private static object GetMemoryCacheLockObject(string key) { string cacheLockKey = (MemoryCacheLockObjectFormat, key); lock (CacheObject) { var lockObject = CacheObject[cacheLockKey]; if (lockObject == null) { // Get the lock object of each Key; if multiple threads require the same data at the same time, they will only check (to the database) for the first time, and the rest will be read from the cache lockObject = new object(); ( cacheLockKey, lockObject, new () { AbsoluteExpiration = (10) } ); } return lockObject; } }
2.2. lock GetMemoryCacheLockObject(key)
public T Get<T>(string key, Func<T> getDataWork, TimeSpan absoluteExpireTime, bool forceRefresh = false, bool returnCopy = true) where T : class { try { lock (GetMemoryCacheLockObject(key)) { /* : Value cannot be null. at (Object obj) at [T](String key, Func`1 getDataWork, TimeSpan absoluteExpireTime, Boolean forceRefresh, Boolean returnCopy) in D:\Source\BQoolCommon\\Cache\:line 46 */ T result = CacheObject[key] as T; if (result != null && forceRefresh) {// Whether to clear the cache, force recheck result = null; } if (result == null) { //Execute the assignment of data acquisition result = getDataWork(); if (result != null) { Set(key, result, absoluteExpireTime); } } if (returnCopy) { //Copy a new reference string serialize = (result); return <T>(serialize); } else { return result; } } } catch { return getDataWork(); } }
Summary and explanation
1. There is data in the cache, just follow the following code and return the result.
T result = CacheObject[key] as T;
2. There is no data in the cache. The first thread entering acquires the lock and retrieves the data from the database. Before releasing the lock, other threads entering parallel will wait and then cache and retrieve the data again. This prevents the occurrence of repeated data fetching in the database and repeated updates to the cache.
try { lock (GetMemoryCacheLockObject(key)) { /* : Value cannot be null. at (Object obj) at [T](String key, Func`1 getDataWork, TimeSpan absoluteExpireTime, Boolean forceRefresh, Boolean returnCopy) in D:\Source\BQoolCommon\\Cache\:line 46 */ T result = CacheObject[key] as T;
3. Obtain the lock object proprietary to each Key; if there are multiple threads at the same time, you will only check (to the database) for the first time, and the rest will be read from the cache.
string cacheLockKey = (MemoryCacheLockObjectFormat, key); lock (CacheObject) { var lockObject = CacheObject[cacheLockKey]; if (lockObject == null) { // Get the lock object of each Key; if multiple threads require the same data at the same time, they will only check (to the database) for the first time, and the rest will be read from the cache lockObject = new object();
The above is the detailed content of how to use lock to solve cache breakdown in c#. For more information about C# lock to solve cache breakdown, please pay attention to my other related articles!