当前位置:网站首页>08_ Spingboot integrated redis

08_ Spingboot integrated redis

2022-06-26 04:23:00 Book opens autumn maple

  • Concurrent : Multiple threads operate on one at the same time ( some ) resources , Bring uncertainty to the data 、 Instability 、 Insecurity
  • Sync : At some point , Only one thread accesses the resource     Solve the concurrency problem , Poor performance ( Programs should not let performance be too low )
  • lock : only     Object monitor
  • Cache wear ( thorn ) Thorough : The cache has ( No, ) data , Access to the database
  • Cache avalanche : At some point , Most of the cache Simultaneous failure , At this time, many threads access concurrently , As a result, the database cannot handle so many accesses and becomes paralyzed
  • assessment   Time sharing invalidation of cache data     Degradation treatment
  • Multithreading : It's not a calculation of data It describes a state

One 、Spring Boot Integrate Redis standalone mode

1.  Case thinking

Perfect according to students id Query the function of students , First from redis cache Search for , If you can't find it , And look it up in the database , Then put redis In cache

2. Implementation steps

First, through MyBatis Reverse engineering generates entities bean And data persistence layer

 A. stay pom.xml Add... To the file redis Dependencies and other configurations

        <!--  load spring boot redis package  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

B. stay Spring Boot Core profile application.properties Middle configuration redis Connection information

server.port=9005
server.servlet.context-path=/005-springboot-redis
# Configuration of database 
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
#redis To configure 
spring.redis.host=192.168.60.130
spring.redis.port=6379
spring.redis.password=123456

C. start-up redis service

[[email protected] /]# cd /usr/local/redis-4.0.6/src/
[[email protected] src]# ./redis-server ../redis.conf &

D. RedisController class

@RestController
public class RedisController {

    @Autowired
    private StudentService studentService;

    /*
     * http://localhost:9005/005-springboot-redis/springboot/allStudentCount
     * */
    @GetMapping(value = "/springboot/allStudentCount")
    public Object allStudentCount(HttpServletRequest request) {

        Long allStudentCount = studentService.queryAllStudentCount();

        return " The total number of students :" + allStudentCount;

    }
}

E. StudentService Interface

public interface StudentService {

    Long queryAllStudentCount();

}

F. stay StudentServiceImpl In the injection RedisTemplate And modify the basis id How to get students

The above steps are configured ,Spring Boot Will be configured automatically RedisTemplate, In need of operation redis In the class of redisTemplate that will do .

Be careful :Spring Boot Help us inject RedisTemplate class , In generics, you can only write <String, String>、<Object, Object> Or write nothing

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Long queryAllStudentCount() {
        // from redis Get the total number of people in the cache 
        Long allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
        // Determine whether it is null 
        if (allStudentCount == null) {
            // Query from database 
            allStudentCount = studentMapper.selectAllStudentCount();
            // Store the value in redis In cache 
            redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 20, TimeUnit.SECONDS);
        }
        return allStudentCount;
    }
}

G. Student Entity class  

public class Student {
    private Integer id;

    private String name;

    private Integer age;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

H. StudentMapper Interface  

@Repository
public interface StudentMapper {

    Long selectAllStudentCount();
}

I. StudentMapper.xml Database configuration file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suke.springboot.mapper.StudentMapper">
    <resultMap id="BaseResultMap" type="com.suke.springboot.model.Student">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
    </resultMap>
    <sql id="Base_Column_List">
        id
        , name, age
    </sql>

    <select id="selectAllStudentCount" resultType="long">
        select count(123)
        from tb_student
    </select>
</mapper>

J. Start class Application

stay SpringBoot Add the annotation of the scan data persistence layer on the startup class and specify the scan package

@SpringBootApplication
@MapperScan("com.suke.springboot.mapper")// Scan data persistence layer 
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

K. start-up SpringBoot application , Access test

 

​​​​​​​L. open Redis Desktop Mananger see Redis Situation in   

Set up 20 Seconds later , The cache disappears

M. stay StudentServiceImpl Add a line of code to solve the garbled code

  Relational database : Data security
 redis: Binary data is secure   Data is serialized directly Store in redis in , At the time of acquisition , Take out the serialized data directly , Anti serialization into objects   There will be no garbled code

// Set up key key , serialize , Function independent 
redisTemplate.setKeySerializer(new StringRedisSerializer());

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Long queryAllStudentCount() {
        // Set up key key , serialize , Function independent 
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // from redis Get the total number of people in the cache 
        Long allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
        // Determine whether it is null 
        if (allStudentCount == null) {
            // Query from database 
            allStudentCount = studentMapper.selectAllStudentCount();
            // Store the value in redis In cache 
            redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 20, TimeUnit.SECONDS);
        }
        return allStudentCount;
    }
}

​​​​​​ Two 、 Cache penetration ​​​​​​​

1. RedisController class

Create a thread pool to simulate the concurrency of thousands of people

@RestController
public class RedisController {

    @Autowired
    private StudentService studentService;

    /*
     * http://localhost:9005/005-springboot-redis/springboot/allStudentCount
     * */
    @GetMapping(value = "/springboot/allStudentCount")
    public Object allStudentCount(HttpServletRequest request) {

        /*Long allStudentCount = studentService.queryAllStudentCount();
        return " The total number of students :" + allStudentCount;*/

        // Creating a thread pool 
        ExecutorService executorService = Executors.newFixedThreadPool(16);
        // Simulate the concurrency of thousands of people 
        for (int i = 0; i < 1000; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    studentService.queryAllStudentCount();
                }
            });
        }
        return " The total number of students :" + 7;
    }
}

 2. StudentServiceImpl class ​​​​​​​

Output at console ” Query the database “ and “ A cache hit ” Display the query results

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Long queryAllStudentCount() {
        // Set up key key , serialize , Function independent 
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // from redis Get the total number of people in the cache 
        Long allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
        // Determine whether it is null 
        if (allStudentCount == null) {
            System.out.println("---- Query the database -----");
            // Query from database 
            allStudentCount = studentMapper.selectAllStudentCount();
            // Store the value in redis In cache 
            redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 20, TimeUnit.SECONDS);
        } else {
            System.out.println("----- A cache hit -------");
        }
        return allStudentCount;
    }
}

3. Start the application , Browser access test

4. Problems caused

Tip: Multiple threads query the database , This phenomenon is called cache penetration , If the concurrency is large , Too much pressure on the database , It may cause database downtime .

3、 ... and 、 Cache penetration - resolvent

1. modify StudentServiceImpl The code in

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public Long queryAllStudentCount() {
        // Set up key key , serialize , Function independent 
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // from redis Get the total number of people in the cache 
        Long allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
        // Judge whether the total number of students is empty 
        if (allStudentCount == null) {
            // Set synchronization code block 
            synchronized (this) {
                // Again from redis Get the total number of students in the cache 
                allStudentCount = (Long) redisTemplate.opsForValue().get("allStudentCount");
                // Double check to determine whether there is data in the cache 
                if (allStudentCount == null) {
                    System.out.println("---- Query the database -----");
                    // Query from database 
                    allStudentCount = studentMapper.selectAllStudentCount();
                    // Store the value in redis In cache 
                    redisTemplate.opsForValue().set("allStudentCount", allStudentCount, 20, TimeUnit.SECONDS);
                } else {
                    System.out.println("----- A cache hit -------");
                }
            }
        } else {
            System.out.println("----- A cache hit -------");
        }
        return allStudentCount;
    }
}

2. Start the application , Browser access test , View console output

Only the first thread queries the database , Other thread queries Redis cache , The small problem to be solved is that the first batch of incoming users will have a wait , But the effect can be ignored

3. springboot Integrate Redis Prevent cache penetration , Why do we need to do double-layer verification

  • Prevent the thread from getting cpu When executing permissions , Other threads have put data into Redis It's in , So judge again
  • Can't be synchronized Expand the scope , Because if Redis If there is data in the cache , Threads should not be synchronized , Otherwise, the efficiency will be affected
  • Solve cache penetration :2 Query cache , Once again, judge
原网站

版权声明
本文为[Book opens autumn maple]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260420207897.html