一、什么是热点数据

在很短的时间内,许多数据要被多次查询(像双十一购物,查询商品)

二、为什么要使用redis

redis是非关系型数据库,Redis将数据存储在内存上,避免了频繁的IO操作,接下来,让大家正真感受下redis的魅力

三、场景

短时间内有大量的请求来获取用户列表的数据,每次都需要从数据库进行查询

1、原思路

技术:SpringBoot+mysql

每次都从mysql数据库中查出对应的数据

代码如下:

entity类(实现序列化接口):

/**
 * 用户实体类
 */
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;

    public User(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

controller层:

/**
 * 控制层
 */
@RestController
public class RedisController {
    @Autowired
    private RedisService redisService;
    @GetMapping("/queryUserList")
    public String queryUserList(){
        long start = System.currentTimeMillis();
        // 采用多线程进行模拟
     ExecutorService fixThreadPool = Executors.newFixedThreadPool(3);
     // 创建执行任务
     Runnable runnable = () -> {
         redisService.queryUserList();
     };

     // 循环执行
     for(int i = 0;i < 10000;i++){
         fixThreadPool.execute(runnable);
     }
     // 用来计算操作时间        fixThreadPool.shutdown();
        long end;
        while(true){
            if(fixThreadPool.isTerminated()) {
                end = System.currentTimeMillis() - start;
                break;
            }
        }

        return "程序运行时间为:"+ end + "毫秒";
    }

}

 

service层:

/**
 * 业务层
 */
@Service
public class RedisService {
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RedisMapper redisMapper;
    public List<User> queryUserList(){
        List<User> userList = redisMapper.queryUserList();
        return userList;
    }
}

dao层:

java:

/**
 * dao层
 */
@Mapper
public interface RedisMapper {
public List<User> queryUserList();
}

xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
                        "https://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.redis.dao.RedisMapper">
    <!-- 查找预约记录列表 -->
    <select id="queryUserList" resultType="com.example.demo.redis.entity.User">
        select * from user
    </select>
</mapper>

运行:

打开浏览器:输入访问地址:http://localhost:8081/queryUserList

查看结果:

SpringBoot+Redis(实现处理热点数据)

 

 

 嗯。。。。。50s,用户体验应该不算太好

 

2、整合redis

思路:

SpringBoot集成redis不再多说,基本思路就是用户首次访问从数据库中取值,之后每次进行判断只要redis中有数据,就从redis中取值,其中涉及到多线程访问早造成的内存穿透问题,采用双重检查的形式解决。

其他层没有变化,业务层的新代码如下:

/**
 * 业务层
 */
@Service
public class RedisService {
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RedisMapper redisMapper;
    public List<User> queryUserList(){
        // 设置序列化
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        List<User> userList = (List<User>)redisTemplate.opsForValue().get("userList");
        // 防止首次访问该接口有大量用户,造成内存穿透,使redis没有效果
        if(null == userList){
            synchronized (this){
                if(null == userList){
                    System.out.println("从mysql中查询数据中。。。。。。");
                    // 从数据库中查询数据
                    userList = redisMapper.queryUserList();
                    System.err.println(userList);
                    // 放入redis
                    redisTemplate.opsForValue().set("userList",userList);
                }
            }
        }else{
            System.out.println("从redis中查询数据中。。。。。。");
        }
        return userList;
    }

再次访问结果如下:

SpringBoot+Redis(实现处理热点数据)

 

 

 比原来的快:18倍左右

这是首次访问呦(需要查一次mysql)

再来访问一次:

SpringBoot+Redis(实现处理热点数据)

 

 

不得不说redis果然快(快了75倍)

四、总结

redis集成SpringBoot用于查询热点数据果然好用,接下来在看看redis的其他应用场景。