c# 如何用lock解决缓存击穿
程序员文章站
2022-06-27 23:43:06
背景缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。解决方案1、设置热点数据...
背景
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案
1、设置热点数据永远不过期。
2、加互斥锁,互斥锁参考代码如下:
2.1、根据key生成object()
private static object getmemorycachelockobject(string key) { string cachelockkey = string.format(memorycachelockobjectformat, key); lock (cacheobject) { var lockobject = cacheobject[cachelockkey]; if (lockobject == null) { // 取得每個 key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取 lockobject = new object(); cacheobject.set( cachelockkey, lockobject, new system.runtime.caching.cacheitempolicy() { absoluteexpiration = datetimeoffset.utcnow.addminutes(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)) { /* system.argumentnullexception: value cannot be null. at system.threading.monitor.enter(object obj) at bqoolcommon.helpers.cache.memorycachelayer.get[t](string key, func`1 getdatawork, timespan absoluteexpiretime, boolean forcerefresh, boolean returncopy) in d:\source\bqoolcommon\bqoolcommon.helpers\cache\memorycachelayer.cs:line 46 */ t result = cacheobject[key] as t; if (result != null && forcerefresh) {// 是否清除cache,強制重查 result = null; } if (result == null) { //執行取得資料的委派作業 result = getdatawork(); if (result != null) { set(key, result, absoluteexpiretime); } } if (returncopy) { //複製一份新的參考 string serialize = jsonconvert.serializeobject(result); return jsonconvert.deserializeobject<t>(serialize); } else { return result; } } } catch { return getdatawork(); } }
总结说明
1、缓存中有数据,直接走下述代码就返回结果了
t result = cacheobject[key] as t;
2、缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
try { lock (getmemorycachelockobject(key)) { /* system.argumentnullexception: value cannot be null. at system.threading.monitor.enter(object obj) at bqoolcommon.helpers.cache.memorycachelayer.get[t](string key, func`1 getdatawork, timespan absoluteexpiretime, boolean forcerefresh, boolean returncopy) in d:\source\bqoolcommon\bqoolcommon.helpers\cache\memorycachelayer.cs:line 46 */ t result = cacheobject[key] as t;
3、取得每个 key专有的 lock object;若同时有多个 thread要求相同资料,只会(到数据库)查第一次,剩下的从 cache读取。
string cachelockkey = string.format(memorycachelockobjectformat, key); lock (cacheobject) { var lockobject = cacheobject[cachelockkey]; if (lockobject == null) { // 取得每個 key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取 lockobject = new object();
以上就是c# 如何用lock解决缓存击穿的详细内容,更多关于c# lock解决缓存击穿的资料请关注其它相关文章!