下面这段代码 如果1W个人同时访问的话, 从redis 拿 allUser 时, userList为空时,那么1W个人都要进入if判断语句,查询数据库,数据库压力承受不住
package com.tb.service;
import com.tb.dao.TUserMapper;
import com.tb.pojo.TUser;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@Transactional
public class TuserServicelmpl implements TuserService {
@Resource
private TUserMapper tUserMapper;
@Resource
private RedisTemplate redisTemplate;
@Override
public List<TUser> userlist() {
//高并发下有点问题,此处问题:缓存穿透
//查询缓存
List<TUser> userList = ( List<TUser>) redisTemplate.opsForValue().get("allUser");
if (userList==null){
//查询数据库
userList = tUserMapper.userlist();
redisTemplate.opsForValue().set("allUser",userList);
}
return userList;
}
}
解决方案
Synchronized 关键字
双重检测锁 解决
package com.tb.service;
import com.tb.dao.TUserMapper;
import com.tb.pojo.TUser;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@Transactional
public class TuserServicelmpl implements TuserService {
@Resource
private TUserMapper tUserMapper;
@Resource
private RedisTemplate redisTemplate;
@Override
public List<TUser> userlist() {
//高并发下有点问题,此处问题:缓存穿透
//查询缓存
List<TUser> userList = ( List<TUser>) redisTemplate.opsForValue().get("allUser");
//双重检测锁
if (userList==null){
synchronized(this){
//从数据库获取数据
userList = ( List<TUser>) redisTemplate.opsForValue().get("allUser");
if (userList==null){
//缓存为空,查询数据库
userList = tUserMapper.userlist();
redisTemplate.opsForValue().set("allUser",userList);
}
}
}
return userList;
}
}
测试代码
@GetMapping("/Tuser")
public List<TUser> querlist(){
//多线程查询数据库
Runnable runnable = new Runnable() {
@Override
public void run() {
tuserService.userlist();
}
};
//新建线程池
ExecutorService executorService = Executors.newFixedThreadPool(25);
for(int i = 0 ; i<10000;i++){
executorService.submit(runnable);
}
return tuserService.userlist();
}