자바 시 뮬 레이 션 및 캐 시 관통 문제 해결
캐 시 관통 은 높 은 동시 다발 에서 만 발생 합 니 다.10000 개가 동시 다발 로 데 이 터 를 조회 할 때 우 리 는 보통 redis 에 가서 데 이 터 를 조회 합 니 다.그러나 redis 에 이 데이터 가 없 을 때 이 10000 개의 동시 다발 안에 많은 부분 이 한꺼번에 my sql 데이터베이스 에 가서 조회 합 니 다.
캐 시 관통 해결
우선 캐 시 관통 시 뮬 레이 션 을 해 보 겠 습 니 다.
예 를 들 어 아래 코드.
Pom.xml 코드
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath></relativePath> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Application.properties
server.port=8081
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://47.91.248.236:3306/hello?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#spring Mybatis
#pojo
mybatis.type-aliases-package=com.itheima.domain
# Mybatis
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
MyController , 10000
/**
* sinture.com Inc.
* Copyright (c) 2016-2018 All Rights Reserved.
*/
package com.itheima.controller;
import com.itheima.mapper.UserMapper;
import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author xinzhu
* @version Id: MyController.java, v 0.1 2018 12 05 6:29 xinzhu Exp $
*/
@RestController
public class MyController {
@Autowired
private UserService userService;
@RequestMapping("/hello/{id}")
@ResponseBody
public User queryUser(@PathVariable Integer id){
//
new Thread(){
@Override
public void run() {
for (int x = 0; x < 10000; x++) {
userService.queryUser(id);
}
}
}.start();
//
return userService.queryUser(id);
}
}
사용자 클래스
/**
* sinture.com Inc.
* Copyright (c) 2016-2018 All Rights Reserved.
*/
package com.itheima.domain;
/**
* @author xinzhu
* @version Id: User.java, v 0.1 2018 12 06 1:40 xinzhu Exp $
*/
public class User {
//
private Integer id;
//
private String username;
//
private String password;
//
private String name;
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
'}';
}
public Integer getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserService
package com.itheima.service;
import com.itheima.domain.User;
public interface UserService {
public User queryUser(Integer id);
}
UserServiceImpl,아래 의 파란색 코드 는 redis 를 모방 하 는 것 입 니 다.이때 아래 의 아 날로 그 redis 의 map 집합 은 아래 query User 의 밖 에 놓 아야 합 니 다.즉,아래 의 userMap 변 수 는 반드시 구성원 변수 여야 합 니 다.그렇지 않 으 면 redis 는 여러 스 레 드 에 의 해 공유 되 기 때 문 입 니 다.아래 의 query User()방법 에 넣 으 면...그러면 여러 스 레 드 에 여러 개의 userMap 집합 이 있 습 니 다.아래 코드 는 데 이 터 를 조회 하면 redis 안에 있 는 것 을 사용 하고 조회 가 안 되면 데이터 베이스 에 있 는 것 을 사용 하 는 것 입 니 다.
package com.itheima.service;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
//
static Map<Integer,User> userMap=new HashMap();
static {
User huancun_user =new User();
huancun_user.setId(1);
huancun_user.setName("zhangsan");
huancun_user.setPassword("123");
huancun_user.setName(" ");
userMap.put(1,huancun_user);
}
//
public User queryUser(Integer id){
User user=userMap.get(id);
if(user==null){
user= userMapper.queryUser(id);
System.out.println(" ");
userMap.put(user.getId(),user);
}else{
System.out.println(" ");
}
return user;
};
}
SpringbootApplication
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
데이터베이스 안의 데 이 터 는 다음 과 같다.
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhangsan', '123', ' ');
INSERT INTO `user` VALUES ('2', 'lisi', '123', ' ');
그 다음 에 우 리 는 아래 의 링크 를 조회 합 니 다.이때 위의 아 날로 그 redis 의 map 집합 에 id 값 이 2 인 데이터 가 없 기 때문에 이때 모두 데이터 베 이 스 를 조회 합 니 다.이번에 10000 을 동시 다발 하면 데이터 베 이 스 는 매우 큰 스트레스 를 받 을 것 이 라 고 생각 합 니 다.그 다음 에 인쇄 결 과 는 다음 과 같다.바로 많은 조회 데이터 베이스 와 조회 캐 시 를 인쇄 한 것 이다.이때 10000 개의 동시 다발 안에 데이터 베 이 스 를 조회 하 는 경우 가 많다 는 것 을 의미한다.이것 은 피해 야 한다.왜 캐 시 를 조회 하 는 인쇄 가 있 는 지 에 대해 우 리 는 조회 한 데 이 터 를 아 날로 그 redis 에 넣 었 기 때문에 처음에 대부분의 스 레 드 는 데이터 베 이 스 를 조회 하 는 것 이다.그리고 나머지 는 아 날로 그 redis 캐 시 에 있 는 데 이 터 를 조회 하 는 것 입 니 다.
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
조회 데이터베이스
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
그리고 우 리 는 이중 검 측 자 물 쇠 를 사용 하여 위의 캐 시 관통 을 해결 합 니 다.
우 리 는 캐 시 관통 을 어떻게 해결 합 니까?10000 개가 병발 되 더 라 도 10000 개의 병발 에 필요 한 데 이 터 는 redis 에 없습니다.그러면 우 리 는 첫 번 째 스 레 드 로 데이터 안의 데 이 터 를 조회 한 다음 에 이 데 이 터 를 redis 에 넣 고 나머지 9999 개의 스 레 드 를 redis 에 넣 어서 조회 해 야 합 니 다.그러면 캐 시 관통 을 해결 할 수 있 습 니 다.그래서 우 리 는 위의 코드 를 아래 처럼 바 꿀 수 있다.
예 를 들 어 아래 코드.
Pom.xml 코드
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath></relativePath> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Application.properties
server.port=8081
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://47.91.248.236:3306/hello?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#spring Mybatis
#pojo
mybatis.type-aliases-package=com.itheima.domain
# Mybatis
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
MyController 코드,아래 파란색 코드 는 10000 개의 병렬 스 레 드 를 모방 합 니 다.
/**
* sinture.com Inc.
* Copyright (c) 2016-2018 All Rights Reserved.
*/
package com.itheima.controller;
import com.itheima.mapper.UserMapper;
import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author xinzhu
* @version Id: MyController.java, v 0.1 2018 12 05 6:29 xinzhu Exp $
*/
@RestController
public class MyController {
@Autowired
private UserService userService;
@RequestMapping("/hello/{id}")
@ResponseBody
public User queryUser(@PathVariable Integer id){
//
new Thread(){
@Override
public void run() {
for (int x = 0; x < 10000; x++) {
userService.queryUser(id);
}
}
}.start();
//
return userService.queryUser(id);
}
}
User
/**
* sinture.com Inc.
* Copyright (c) 2016-2018 All Rights Reserved.
*/
package com.itheima.domain;
/**
* @author xinzhu
* @version Id: User.java, v 0.1 2018 12 06 1:40 xinzhu Exp $
*/
public class User {
//
private Integer id;
//
private String username;
//
private String password;
//
private String name;
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
'}';
}
public Integer getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserService
package com.itheima.service;
import com.itheima.domain.User;
public interface UserService {
public User queryUser(Integer id);
}
UserServiceImpl,아래 의 파란색 코드 는 redis 를 모방 하 는 것 입 니 다.이때 아래 의 아 날로 그 redis 의 map 집합 은 아래 query User 의 밖 에 놓 아야 합 니 다.즉,아래 의 userMap 변 수 는 반드시 구성원 변수 여야 합 니 다.그렇지 않 으 면 redis 는 여러 스 레 드 에 의 해 공유 되 기 때 문 입 니 다.아래 의 query User()방법 에 넣 으 면...그러면 여러 스 레 드 에 여러 개의 userMap 집합 이 있 습 니 다.아래 코드 는 데 이 터 를 조회 하면 redis 안에 있 는 것 을 사용 하고 조회 가 안 되면 데이터 베이스 에 있 는 것 을 사용 하 는 것 입 니 다.그 다음 에 아래 의 빨간색 코드 는 바로 위의 캐 시 관통 문 제 를 해결 하 는 것 입 니 다.자 물 쇠 를 사용 하여 캐 시 관통 문 제 를 해결 하 는 것 입 니 다.그리고 이중 검 측 자물쇠 라 고 합 니 다.왜 이중 검 측 자물쇠 라 고 합 니까?두 개의 if 문구 가 있 기 때문에 첫 번 째 if 문 구 는 빨간색 코드 안의 동기 코드 블록 을 줄 이기 위해 서 입 니 다.안에 원 하 는 데이터 가 존재 하기 때 문 입 니 다.그러면 아래 의 빨간색 코드 에 있 는 동기 코드 블록 을 걸 을 필요 가 없습니다.그래서 두 개의 if 문구 가 있 습 니 다.왜 아래 의 user=userMap.get(id)이 있어 야 하 는 지 에 대해 서 는...첫 번 째 스 레 드 조회 에서 데 이 터 를 모방 한 redis 캐 시 에 넣 은 후에 남 은 스 레 드 가 아래 의 동기 코드 블록 으로 갈 때 캐 시 에 있 는 데 이 터 를 조회 해 야 방금 첫 번 째 스 레 드 가 redis 에 있 는 데 이 터 를 발견 할 수 있 기 때문에 아래 의 빨간색 코드 에 있 는 user=userMap.get(id)이 있 습 니 다.
package com.itheima.service;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
//
static Map<Integer,User> userMap=new HashMap();
static {
User huancun_user =new User();
huancun_user.setId(1);
huancun_user.setName("zhangsan");
huancun_user.setPassword("123");
huancun_user.setName(" ");
userMap.put(1,huancun_user);
}
//
public User queryUser(Integer id){
User user=userMap.get(id);
//
if(user==null){
synchronized (this) {
user= userMap.get(id);
if (null == user) {
user= userMapper.queryUser(id);
System.out.println(" ");
userMap.put(user.getId(),user);
}else{
System.out.println(" ");
}
}
}else{
System.out.println(" ");
}
//
return user;
};
}
데이터베이스 안의 데 이 터 는 다음 과 같다.
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhangsan', '123', ' ');
INSERT INTO `user` VALUES ('2', 'lisi', '123', ' ');
그 다음 에 우 리 는 아래 의 링크 를 조회 합 니 다.이때 위의 아 날로 그 redis 의 map 집합 에 id 값 이 2 인 데이터 가 없 기 때문에 이때 모두 데이터 베 이 스 를 조회 합 니 다.이번에 10000 을 동시 다발 하면 데이터 베 이 스 는 매우 큰 스트레스 를 받 을 것 이 라 고 생각 합 니 다.그리고 인쇄 결 과 는 다음 과 같 습 니 다.바로 첫 번 째 로 조회 데이터 베 이 스 를 인쇄 한 다음 에 나머지 는 모두 캐 시 를 조회 하 는 것 입 니 다.이것 이 바로 캐 시 관통 을 해결 하 는 것 입 니 다.
조회 데이터베이스
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
캐 시 조회
총결산
위 에서 말 한 것 은 편집장 이 여러분 에 게 소개 한 자바 시 뮬 레이 션 과 캐 시 관통 문 제 를 해결 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 메 시 지 를 남 겨 주세요.편집장 은 신속하게 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
만약 당신 이 본문 이 당신 에 게 도움 이 된다 고 생각한다 면,전 재 를 환영 합 니 다.번 거 로 우 시 겠 지만 출처 를 밝 혀 주 십시오.감사합니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.