简述:
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),缓存在某个时间点过期的时候,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力,可能瞬间把后台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--给调用线程赋予互斥体的初始所属权//第一个参数:互斥体的名称//第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回trueif (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





