服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 如何用lock解决缓存击穿

c# 如何用lock解决缓存击穿

2022-10-31 11:39UP技术控 C#

这篇文章主要介绍了c# 如何用lock解决缓存击穿,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下

背景

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

解决方案

1、设置热点数据永远不过期。

2、加互斥锁,互斥锁参考代码如下:

2.1、根据key生成object()

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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、缓存中有数据,直接走下述代码就返回结果了

?
1
T result = CacheObject[key] as T;

2、缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。

?
1
2
3
4
5
6
7
8
9
10
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读取。

?
1
2
3
4
5
6
7
8
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解决缓存击穿的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/lyl6796910/p/14354503.html

延伸 · 阅读

精彩推荐
  • C#Unity实现角色受击身体边缘发光特效

    Unity实现角色受击身体边缘发光特效

    这篇文章主要为大家详细介绍了Unity实现角色受击身体边缘发光特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    林新发4082022-09-01
  • C#Winform界面中实现菜单列表的动态个性化配置管理方法

    Winform界面中实现菜单列表的动态个性化配置管理方法

    下面小编就为大家分享一篇Winform界面中实现菜单列表的动态个性化配置管理方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    伍华聪3282022-02-13
  • C#C# protobuf自动更新cs文件

    C# protobuf自动更新cs文件

    这篇文章主要介绍了C# protobuf自动更新cs文件的相关资料,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...

    egmkang4952022-08-24
  • C#C#中图片、二进制与字符串的相互转换方法

    C#中图片、二进制与字符串的相互转换方法

    这篇文章主要介绍了C#中图片、二进制与字符串的相互转换方法,涉及C#针对不同数据类型的解析与转换操作技巧,需要的朋友可以参考下...

    smartsmile20124612021-11-25
  • C#C#操作Word打印的示例

    C#操作Word打印的示例

    这篇文章主要介绍了C#操作Word打印的示例,帮助大家利用c#打印文件,提高办公效率,感兴趣的朋友可以了解下...

    一只独行的猿9682022-10-12
  • C#浅析C#中StringBuilder类的高效及与String的对比

    浅析C#中StringBuilder类的高效及与String的对比

    StringBuilder类所创造出来的字符串对象在拼接操作等方面比普通的string类往往要高效很多,这是它们在内存划分方式上的不同所决定的,下面就来浅析C#中Stri...

    吉吉于9722021-11-22
  • C#C#在图片增加文字的实现代码

    C#在图片增加文字的实现代码

    最近做项目需要动态给图片增加文字(书本的封面图片),修改字体大小、字体、颜色、控制位置等,下面通过实例代码给大家分享C#在图片增加文字的实...

    空空隆隆4482022-01-10
  • C#使用C#正则表达式获取必应每日图片地址

    使用C#正则表达式获取必应每日图片地址

    这篇文章主要介绍了使用C#正则表达式获取必应每日图片地址的相关资料,需要的朋友可以参考下...

    ssz6667062021-12-31