zoukankan      html  css  js  c++  java
  • 解决高并发下的缓存穿透问题

      目前我们针对高并发场景,这种问题很常见,一般有如下两种解决方式:

      一:在方法上加上同步锁 synchronized(用的比较少)

      

        //加同步锁,解决高并发下缓存穿透
        @Test
        public synchronized void getMyUser(){
            //字符串的序列化器 redis
            RedisSerializer redisSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(redisSerializer);
            //查询缓存
            MyUser myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
            if(null == myUser){
                System.out.println("当缓存没有myUser时显示.");
                //缓存为空,查询数据库
                myUser = myUserMapper.selectByPrimaryKey(1l);
                //把数据库查询出来的数据放入redis
                redisTemplate.opsForValue().set("myUser",myUser);
            }
            System.out.println(myUser);
        }

      二:使用双重检测锁(常用)

      

     public void getMyUser(){
            //字符串的序列化器 redis
            RedisSerializer redisSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(redisSerializer);
            //查询缓存
            MyUser myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
    
            //双层检测锁
            if(null == myUser){
                synchronized(this){
                    myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
                    if(null == myUser){
                        System.out.println("当缓存没有myUser时显示.");
                        //缓存为空,查询数据库
                        myUser = myUserMapper.selectByPrimaryKey(1l);
                        //把数据库查询出来的数据放入redis
                        redisTemplate.opsForValue().set("myUser",myUser);
                    }
                }
            }
    
    
            System.out.println(myUser);
        }

      三:进行高并发测试

      

    import com.ykmimi.job.bean.MyUser;
    import com.ykmimi.job.mapper.MyUserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    @RestController
    public class MyUserController {
    
        @Autowired
        private RedisTemplate<Object,Object> redisTemplate;
        @Resource
        private MyUserMapper myUserMapper;
    
        public Integer insertNew(){
    
            return 0;
        }
    
        @RequestMapping("/getMyUserTest")
        public void getMyUserTest(){
            //线程,该线程调用底层查询MyUser的方法
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    getMyUser();
                }
            };
    
            //多线程测试一下缓存穿透的问题
            ExecutorService executorService = Executors.newFixedThreadPool(25);
            for(int i=0;i<10000;i++){
                executorService.submit(runnable);
            }
    
        }
    
        public void getMyUser(){
            //字符串的序列化器 redis
            RedisSerializer redisSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(redisSerializer);
            //查询缓存
            MyUser myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
    
            //双层检测锁
            if(null == myUser){
                System.out.println("当缓存没有myUser时显示.没有进入同步锁");
                synchronized(this){
                    myUser = (MyUser) redisTemplate.opsForValue().get("myUser");
                    if(null == myUser){
                        System.out.println("当缓存没有myUser时显示.已经进入同步锁");
                        //缓存为空,查询数据库
                        myUser = myUserMapper.selectByPrimaryKey(1l);
                        //把数据库查询出来的数据放入redis
                        redisTemplate.opsForValue().set("myUser",myUser);
                    }
                }
            }
    
            System.out.println(myUser);
        }
    
    
    }

      住:线程池中不要特别大的线程

      

  • 相关阅读:
    使用XUACompatible来设置IE8兼容模式[转]
    XML Sitemaps 格式
    A Link 链接的rel、target属性详解
    IE与Firefox等浏览器对容器width的不同解释及解决办法
    超越文档类型,web标准化向前兼容和IE8
    MSSQL、MYSQL,ACCESSl,Oracle随机读取N条记录方法
    IE8如何定义浏览器工作模式避免网页显示混乱
    什么是SVN? 什么是CVS? SVN跟CVS又有什么关系呢?
    2008年度75套最佳网页设计资源
    一组JS创建和操作表格的函数集合
  • 原文地址:https://www.cnblogs.com/wangzhengyu/p/10621464.html
Copyright © 2011-2022 走看看