redis缓存穿透,缓存击穿,缓存雪崩原因( 二 )

其它方案:待各位补充 。
05缓存雪崩解决方案与缓存击穿的区别在于这里针对很多key缓存,前者则是某一个key 。
缓存正常从Redis中获取,示意图如下:
 

redis缓存穿透,缓存击穿,缓存雪崩原因

文章插图
 
 
缓存失效瞬间示意图如下:
 
redis缓存穿透,缓存击穿,缓存雪崩原因

文章插图
 
 
缓存失效时的雪崩效应对底层系统的冲击非常可怕!大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上 。还有一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件 。
加锁排队,伪代码如下:
//伪代码public object GetProductListNew() { int cacheTime = 30; String cacheKey = "product_list"; String lockKey = cacheKey; String cacheValue = https://www.isolves.com/it/sjk/Redis/2019-08-26/CacheHelper.get(cacheKey); if (cacheValue != null) { return cacheValue; } else { synchronized(lockKey) { cacheValue = CacheHelper.get(cacheKey); if (cacheValue != null) { return cacheValue; } else { //这里一般是sql查询数据 cacheValue = GetProductListFromDB();CacheHelper.Add(cacheKey, cacheValue, cacheTime); } } return cacheValue; }}加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量 。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的 。同样会导致用户等待超时,这是个治标不治本的方法!
注意:加锁排队的解决方式分布式环境的并发问题,有可能还要解决分布式锁的问题;线程还会被阻塞,用户体验很差!因此,在真正的高并发场景下很少使用!
随机值伪代码:
//伪代码public object GetProductListNew() { int cacheTime = 30; String cacheKey = "product_list"; //缓存标记 String cacheSign = cacheKey + "_sign"; String sign = CacheHelper.Get(cacheSign); //获取缓存值 String cacheValue = https://www.isolves.com/it/sjk/Redis/2019-08-26/CacheHelper.Get(cacheKey); if (sign != null) { return cacheValue; //未过期,直接返回 } else { CacheHelper.Add(cacheSign, "1", cacheTime); ThreadPool.QueueUserWorkItem((arg) -> { //这里一般是 sql查询数据 cacheValue = GetProductListFromDB();//日期设缓存时间的2倍,用于脏读 CacheHelper.Add(cacheKey, cacheValue, cacheTime * 2);}); return cacheValue; }} 解释说明:
  • 缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际key的缓存;
  • 缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟 。这样,当缓存标记key过期后,实际缓存还能把旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存 。
关于缓存崩溃的解决方法,这里提出了三种方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一种被称为“二级缓存”的解决方法 。
06小结针对业务系统,永远都是具体情况具体分析,没有最好,只有最合适 。
于缓存其它问题,缓存满了和数据丢失等问题,大伙可自行学习 。最后也提一下三个词LRU、RDB、AOF,通常我们采用LRU策略处理溢出,Redis的RDB和AOF持久化策略来保证一定情况下的数据安全 。
参考相关链接:
https://blog.csdn.net/zeb_perfect/article/details/54135506
https://blog.csdn.net/fanrenxiang/article/details/80542580
https://baijiahao.baidu.com/s?id=1619572269435584821&wfr=spider&for=pc
https://blog.csdn.net/xlgen157387/article/details/79530877
END!
请留下你指尖的温度
让太阳拥抱你
记得这是一个有温度的头条号
print_r('点个好看吧!');
var_dump('点个好看吧!');
NSLog(@"点个好看吧!");
System.out.println("点个好看吧!");
console.log("点个好看吧!");
print("点个好看吧!");
printf("点个好看吧!n");
cout << "点个好看吧!" << endl;
Console.WriteLine("点个好看吧!");
fmt.Println("点个好看吧!");
Response.Write("点个好看吧!");
alert("点个好看吧!")
echo"点个好看吧!"

【redis缓存穿透,缓存击穿,缓存雪崩原因】


推荐阅读