Redis缓存击穿、缓存穿透、缓存雪崩原理及解决方案
【摘要】
文章目录
一.前言二.缓存击穿(1)概念(2)如何解决
三.缓存穿透(1)概念(2)如何解决
四.缓存雪崩(1)概念(2)如何解决
一.前言
Redis缓...
一.前言
- Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解
- 如果对数据的一致性要求很高,那么就不能使用缓存。在缓存使用的过程中也存在一些典型的问题:
缓存击穿、缓存穿透、缓存雪崩
。
二.缓存击穿
(1)概念
- 缓存击穿:大并发集中对某一数据进行访问,并且缓存中不存在访问的数据(第一次访问或者缓存过期),持续的大并发就穿破缓存,直接请求数据库。
(2)如何解决
- 双重检测锁机制(提升效率)
//ItemService
public Item queryItemById(String itemId){
Item item = itemCacheHander.getItemFromCache(itemId);
if(item == null) {
synchronized (this) {
item = itemCacheHander.getItemFromCache(itemId);
if (item == null) {
System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐查询数据库");
item = itemDAO.queryItem(itemId);
itemCacheHander.addItemToCache(item);
}
}
}
return item;
}
- 步骤小结:
- ①高并发情况下,当第一次访问的时候先从缓存数据库中查询,如果为空
- ②同步锁锁住
- ③再次从缓存中查询是否为空(这里只有第一个到达的访问会继续进行下一步,因为缓存中没有)
- ④第一个到达的访问会从再次判断为空,从数据库中查询,查询完结果放入缓存当中
- ⑤从第二个当达的访问开始每一个都可以从缓存中查取
- ⑥从而避免大量访问同时进入导致数据库崩掉的情况。
补充:synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。
三.缓存穿透
(1)概念
- 缓存穿透,是指查询一个数据库不存在的数据。首先查询缓存,缓存中不存在则查询数据库,数据查询到的数据依然为空,设置到缓存中也为空;因此后续所有对次数据的查询都会先查询缓存,缓存不存在继而又查询数据库。
案例:(想象一下这个情况,如果传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象。就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。)
(2)如何解决
- 即使数据库查询为空,也向缓冲中写入非空值
解决缓存穿透的思路就是:如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。
- ItemCacheHandler(缓存帮助类)
/**
* 存缓存
* @param item
*/
public void addItemToCacheEx(Item item){
String json = new Gson().toJson(item);
//设置过期时间
redisTemplate.boundValueOps("item‐"+item.getItemId()).set(json,5);
}
- ItemService
//查询操作
public Item queryItemById(String itemId){
Item item = itemCacheHander.getItemFromCache(itemId);
if(item == null) {
synchronized (this) {
item = itemCacheHander.getItemFromCache(itemId);
if (item == null) {
System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐查询数据库");
item = itemDAO.queryItem(itemId);
// 如果从数据库查询信息为null,则创建一个对象写入到缓冲,并设置过期时间
if(item == null) {
item = new Item();
item.setItemId(itemId);
itemCacheHander.addItemToCacheEx(item);
}else {
itemCacheHander.addItemToCache(item);
}
}
}
}
return item;
}
- 步骤小结
- ①高并发大量访问进来,先从缓存中查取若为空
- ②同步锁从缓存中再次查如为空
- ③执行从数据库中查询
- ④如果从数据库查询信息为null,则创建一个对象写入到缓冲,并设置过期时间
- ⑤返回结果
四.缓存雪崩
(1)概念
- 缓存雪崩,是指在某一个时间段,缓存集中过期失效,则大量的并发访问查询都落到了数据库上。
案例:例如马上就要到双十一零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
(2)如何解决
- 1.
一般是采取不同分类商品,缓存不同周期。
在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目的商品缓存时间长一些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源
其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么那个时候数据库能顶住压力,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
- 2.如果缓存数据库是分布式,
可以将热点数据均匀随机分布在不同的缓存数据库中,对于热点数据可以设置不过期等.
Please enjoy the pain which is unable to avoid.
2020.03.06
文章来源: blessing.blog.csdn.net,作者:辰兮要努力,版权归原作者所有,如需转载,请联系作者。
原文链接:blessing.blog.csdn.net/article/details/104693904
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)