暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

项面试必备:开发项目中出现过缓存击穿吗,简单说说怎么发生的?

DotNet开发跳槽 2021-07-22
267

简述:

      缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),缓存在某个时间点过期的时候,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力,可能瞬间把后台DB挂掉。

解决方案:

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

缺点:会造成写一致问题,当数据库数据发生更新时,缓存中的数据不会及时更新,这样会造成数据库中的数据与缓存中的数据的不一致,应用会从缓存中读取到脏数据。可采用延时双删策略处理。

2、加二级缓存,采用 L1 (一级缓存)和 L2(二级缓存) 缓存方式,L1 缓存失效时间短,L2 缓存失效时间长。请求优先从 L1 缓存获取数据,如果 L1缓存未命中则加锁,只有 1 个线程获取到锁,这个线程再从数据库中读取数据并将数据再更新到到 L1 缓存和 L2 缓存中,而其他线程依旧从 L2 缓存获取数据并返回。

3、加互斥锁,在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。

互斥锁解决方案:


    using System;
    using System.Threading;


    namespace ConsoleApp1
    {
    class shareRes
    {
    public static int count = 0;
    public static Mutex mutex = new Mutex();
    }


    class IncThread
    {
    int number;
    public Thread thrd;
    public IncThread(string name, int n)
    {
    thrd = new Thread(this.run);
    number = n;
    thrd.Name = name;
    thrd.Start();
    }
    void run()
    {
    Console.WriteLine(thrd.Name + "正在等待 the mutex");
    申请
    shareRes.mutex.WaitOne();
    Console.WriteLine(thrd.Name + "申请到 the mutex");
    do
    {
    Thread.Sleep(1000);
    shareRes.count++;
    Console.WriteLine("In " + thrd.Name + "ShareRes.count is " + shareRes.count);
    number--;
    } while (number > 0);
    Console.WriteLine(thrd.Name + "释放 the nmutex");
    释放
    shareRes.mutex.ReleaseMutex();
    }
    }
    class DecThread
    {
    int number;
    public Thread thrd;
    public DecThread(string name, int n)
    {
    thrd = new Thread(this.run);
    number = n;
    thrd.Name = name;
    thrd.Start();
    }
    void run()
    {
    Console.WriteLine(thrd.Name + "正在等待 the mutex");
    申请
    shareRes.mutex.WaitOne();
    Console.WriteLine(thrd.Name + "申请到 the mutex");
    do
    {
    Thread.Sleep(1000);
    shareRes.count--;
    Console.WriteLine("In " + thrd.Name + "ShareRes.count is " + shareRes.count);
    number--;
    } while (number > 0);
    Console.WriteLine(thrd.Name + "释放 the nmutex");
    释放
    shareRes.mutex.ReleaseMutex();
    }
    }


    class Program
    {
    static void Main(string[] args)
    {
    IncThread mthrd1 = new IncThread("线程1 thread ", 5);
    DecThread mthrd2 = new DecThread("线程2 thread ", 5);
    mthrd1.thrd.Join();
    mthrd2.thrd.Join();
    Console.Read();
    }
    }
    }

    关于互斥锁解决方案,我们可以通过了解互斥锁(Mutex)来进行解决。

    扩展:

    互斥锁(Mutex)

    互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它。

    互斥锁可适用于一个共享资源每次只能被一个线程访问的情况

     函数:

    //创建一个处于未获取状态的互斥锁

    Public Mutex();

    //如果owned为true,互斥锁的初始状态就是被主线程所获取,否则处于未获取状态

     Public Mutex(bool owned);

     如果要获取一个互斥锁。应调用互斥锁上的WaitOne()方法,该方法继承于Thread.WaitHandle类

    它处于等到状态直至所调用互斥锁可以被获取,因此该方法将组织住主调线程直到指定的互斥锁可用,如果不需要拥有互斥锁,用ReleaseMutex方法释放,从而使互斥锁可以被另外一个线程所获取

    //Public Mutex(bool owned,name,out flag);

    name为互斥量的名字,也就是说在操作系统中只有一个命名为name的互斥量mutex,如果一个线程得到这个name的互斥锁,其他线程就无法得到这个互斥锁了,必须等待那个线程对这个线程释放

    参考别人的博客的代码实验

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading;


      namespace myConApp
      {
      class Test
      {
      /// <summary>
      /// 应用程序的主入口点。
      /// </summary>
      [STAThread]
      static void Main(string[] args)
      {
      bool flag = false;
      System.Threading.Mutex mutex = new System.Threading.Mutex(true, "Test", out flag);
      //第一个参数:true--给调用线程赋予互斥体的初始所属权
      //第一个参数:互斥体的名称
      //第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true
      if (flag)
      {
      Console.Write("Running");
      }
      else
      {
      Console.Write("Another is Running");
      System.Threading.Thread.Sleep(5000);//线程挂起5秒钟
      Environment.Exit(1);//退出程序
      }
      Console.ReadLine();


      }
      }
      }

       运行以上代码生成的应用程序第一个实例,会得到结果

      Running
       保持第一个运行状态,运行第二个实例,得到结果

      Another is Running
       以上代码中创建了一个mutex,从其参数的解释中得知,第一个调用线程将得到互斥体的初始所属权,如果不释放的话,其他的线程得不到互斥体所有权。

      引用1:https://www.cnblogs.com/chenwolong/p/13433982.html

      引用2:https://www.cnblogs.com/yeshenmeng/p/9620792.html


      版权申明:本文来源于网友收集或网友提供,仅供学习交流之用,如果有侵权,请转告版主或者留言,本公众号立即删除。


      支持小微:

      腾讯云 搞活动了?玩服务器的可以搞搞。就这几天时间。

      轻量  1C2G6M 60GB SSD盘297元/3年

      链接:https://curl.qcloud.com/bR8ycXZa



      右下角,您点一下在看图片

      小微工资涨1毛

      商务合作QQ:185601686





      文章转载自DotNet开发跳槽,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论