Redis:解决缓存穿透问题

redis相关面试题:

1.redis支持哪些数据类型?String List Hash(Map) Set StoredSet(有排序Set)

2.这些数据类型使用的时候怎么用?

String:建议存储比较独立的数据,并且多个String没有关联
List:建议存储有顺序要求的数据
Hash:存储key-value数据,并且他们有关联关系,存储一个对象数据
Set:存储无序数据,要求没有重复
StoredSet:有序Set,存储例如排行榜数据,每个元素有权重

3.为什么使用redis?快
redis:内存cpu的性能
数据库:磁盘读写性能

4.有点:数据结构简单,key-value
nosql,非关系数据

5.常见问题:
缓存穿透:
是指查询一个存在的数据,由于cache不命中,没有一个请求提前往redis中放数据,都去数据库查,
造成系统性能下降
=================修改之前的代码
/**缓存穿透:
* 1.假设有10000个人同时并发调用这段代码,结果都没有命中
*/
List userList=(List) redisTemplate.opsForValue().get(“userList”);
if(null
userList)
{
System.out.println(“去数据库拿”);
//缓存没有去数据库拿
/**
* 2.结果10000个请求都去访问数据库,从数据库查询数据(需要时间长,用户体验稍微不好),这就是鼎鼎有名的缓存穿透
*/
userList=userMapper.selectAll();
//拿了之后放入缓存
redisTemplate.opsForValue().set(“userList”, userList);
}else
{
System.out.println(“从缓存中拿”);
}
return userList;

=============这是controller中原来的代码:
ModelAndView mav=new ModelAndView();
mav.setViewName(“list”);//springboot工程跳转html的路径默认前缀是 templates目录,后缀是.html,
mav.addObject(“userList”, userServiceIfac.getAllUser());
return mav;

==========================可以采用双重检测来改进缓存穿透问题
service代码:

List userList=(List) redisTemplate.opsForValue().get(“userList”);
if(nulluserList)//第一次检测
{
//缓存没有去数据库拿
/**
* 2.结果10000个请求都去访问数据库,从数据库查询数据(需要时间长,用户体验稍微不好),这就是鼎鼎有名的缓存穿透
*/
synchronized (this) {//synchronized能够把并发执行的代码变得同步执行,也就是顺序执行
userList=(List) redisTemplate.opsForValue().get(“userList”);
if(null
userList) {//第二次检测
System.out.println(“去数据库拿”);
userList=userMapper.selectAll();
//拿了之后放入缓存
redisTemplate.opsForValue().set(“userList”, userList);
}else
{
System.out.println(“从缓存中拿”);
}
}
}else
{
System.out.println(“从缓存中拿”);
}
return userList;

controller中模拟并发请求的代码:
@RequestMapping(“listUser”)
public ModelAndView listUser()
{
//模拟在当次请求中并发调用getAllUser方法10000次
// ModelAndView mav=new ModelAndView();
// mav.setViewName(“list”);//springboot工程跳转html的路径默认前缀是 templates目录,后缀是.html,
// mav.addObject(“userList”, userServiceIfac.getAllUser());
ModelAndView mav=new ModelAndView();

	//1.首先要有一个线程,多个线程的同时启动,那就是并发执行
	Runnable r=new Runnable() {
		
		@Override
		public void run() {
			userServiceIfac.getAllUser();
		}
	};
	
	//2.模拟一个线程池,执行10000次提交
	ExecutorService executorService=Executors.newFixedThreadPool(25);
	for(int i=0;i<10000;i++)
	{
		executorService.submit(r);
	}
	mav.setViewName("list");
	mav.addObject("userList", null);
	return mav;
}

====================缓存击穿
1.如果缓存和数据库中都没有数据,那么用户一直恶意请求怎么办?
那么就给数据一个默认值,这个默认值也可以是一个标识,标识这个数据没有,不用再查了

缓存雪崩:
是指cache设置了相同的过期时间,导致cache在同一时间失效,请求全部转发到DB,造成DB压力过大
瞬间雪崩,给key设置不同的过期时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值