springboot下redis高并发下的缓存穿透

@RequestMapping("/getClass/{id}")
	public @ResponseBody String getClassesById(@PathVariable("id") Integer id){
		RedisSerializer redisSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(redisSerializer);
		Classes classes = (Classes)redisTemplate.opsForValue().get("classes");
		if (null == classes || "".equals(classes)) {
			Classes classesById = classesServer.getClassesById(id);
			redisTemplate.opsForValue().set("classes", classesById);
			return classesById+"从数据库拿";
		}
		return redisTemplate.opsForValue().get("classes")+"从redis中拿";
		

这样看单机条件下没有问题但是高并发下还是会存在多个用户到数据库中查找数据

简单点的是可以在方法中加锁

@RequestMapping("/getClass/{id}")
	public @ResponseBody synchronized String getClassesById(@PathVariable("id") Integer id){
		RedisSerializer redisSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(redisSerializer);
		Classes classes = (Classes)redisTemplate.opsForValue().get("classes");
		if (null == classes || "".equals(classes)) {
			Classes classesById = classesServer.getClassesById(id);
			redisTemplate.opsForValue().set("classes", classesById);
			return classesById+"从数据库拿";
		}
		return redisTemplate.opsForValue().get("classes")+"从redis中拿";
	}

但是这样会牺牲部分性能,可以再细化一下加锁位置,会稍微提高一点性能

@RequestMapping("/getClass/{id}")
	public @ResponseBody synchronized String getClassesById(@PathVariable("id") Integer id){
		RedisSerializer redisSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(redisSerializer);
		Classes classes = (Classes)redisTemplate.opsForValue().get("classes");
		if (null == classes) {
			synchronized (this) {
				classes = (Classes)redisTemplate.opsForValue().get("classes");
				
				if (null == classes || "".equals(classes)) {
					Classes classesById = classesServer.getClassesById(id);
					redisTemplate.opsForValue().set("classes", classesById);
					return classesById+"从数据库拿";
				}
			}
		}
		return redisTemplate.opsForValue().get("classes")+"从redis中拿";
	}
	

 

你可能感兴趣的:(springboot)