当前位置:网站首页>MySQL performance optimization (6): read write separation
MySQL performance optimization (6): read write separation
2022-06-30 03:27:00 【The undead bird Alexander. brutal young person】
1 Schematic diagram

- A connection pool can only operate on one database , Now our project has multiple databases , You must configure the corresponding connection pool for each database
- In execution SQL Use of statements , Select which connection pool to use according to the operation performed , Such as : perform DML You have to choose MasterDataSource To operate , perform DQL The operation is to choose SlaveDataSource To operate
- At this point there should be another object , This object has the function of managing all connection pools and selecting connection pools for use , This object is the connection pool with routing function
- When the caller needs to perform database operations , Then tell the routing connection pool that I need you to help me choose which connection pool to operate the database
2 Implementation steps
The structure is as follows :

Code download address :
mysql Read write separation demonstration -Java Document resources -CSDN download
2.1 newly build springboot Project import dependency
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.3</version>
<!-- <scope>runtime</scope>-->
</dependency>
</dependencies>2.2 Customize a tool class , Used to mark when selecting connection pool operation , Bind to the current thread
package com.example.util;
// Routing helps us select the tool class of connection pool
public abstract class RoutingUtil {
private static ThreadLocal<String> local = new ThreadLocal<>();
public static void setMaster(){
//get,list,query At the beginning of the query rule method, you should set slave, Other cases are set to master
local.set("master");
System.out.println(" Set up master");
}
public static void setSlave(){
//get,list,query At the beginning of the query rule method, you should set slave, Other cases are set to master
local.set("slave");
System.out.println(" Set up slave");
}
public static Object getRoutingOption(){
return local.get();
}
}
2.3 Customize a routing connection pool , Inherit Spring Provided AbstractRoutingDataSource
package com.example.util;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
// The routing connection pool of the current project
public class SkywalkingRoutingDataSource extends AbstractRoutingDataSource {
// How to select a connection pool
@Override
protected Object determineCurrentLookupKey() {
Object key = RoutingUtil.getRoutingOption();
return key;
}
}
2.4 Configuration object DataSourceConfig Configure connection pool
package com.example.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.example.util.SkywalkingRoutingDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
// Connection pool configuration object
@Configuration
public class DataSourceConfig {
// Create a connection pool for each database
// 1 Operations Master 1 individual Slave
// 1 A connection pool with routing function
@Bean(initMethod = "init", destroyMethod = "close")
public DataSource masterDataSource() {
DruidDataSource master = new DruidDataSource();
master.setUrl("jdbc:mysql://192.168.222.131:3306/skywalking");
master.setUsername("root");
master.setPassword("123456");
return master;
}
@Bean(initMethod = "init", destroyMethod = "close")
public DataSource slaveDataSource() {
DruidDataSource slave = new DruidDataSource();
slave.setUrl("jdbc:mysql://192.168.222.130:3306/skywalking");
slave.setUsername("root");
slave.setPassword("123456");
return slave;
}
// Connection pool with routing function , This object is really exposed to be used
@Bean
public DataSource routingDataSource(DataSource masterDataSource, DataSource slaveDataSource) {
Map<Object, Object> map = new HashMap<>();
map.put("master", masterDataSource);
map.put("slave", slaveDataSource);
SkywalkingRoutingDataSource skywalkingRoutingDataSource = new SkywalkingRoutingDataSource();
// Manage which connection pools
skywalkingRoutingDataSource.setTargetDataSources(map);
// Set the default connection pool
skywalkingRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
return skywalkingRoutingDataSource;
}
}
2.5 To configure MyBatis The core object
package com.example.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@MapperScan("com.example.mapper")
@EnableTransactionManagement
public class MyBatisConfig {
@Autowired
private DataSource routingDataSource;
// establish sqlsessionFactory
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception{
SqlSessionFactoryBean factoryBean =new SqlSessionFactoryBean();
factoryBean.setDataSource(routingDataSource);
factoryBean.setTypeAliasesPackage("com.example.domain");
return factoryBean.getObject();
}
// Create transaction manager
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(routingDataSource);
}
}
2.6 Use AOP The method decouples the logic of route selection in the business layer
package com.example.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
// Set the priority of the facet proxy
@Order(1)
@Component
public class RoutingAopAspect {
@Pointcut("execution(* com.example.service.impl.*ServiceImpl.*(..))")
public void pc() {
}
@Before("pc()")
public void setRouting(JoinPoint point) {
// According to the currently executed method , To decide which one to set key
String methodName = point.getSignature().getName();
if (isSlave(methodName)) {
RoutingUtil.setSlave();
}else{
RoutingUtil.setMaster();
}
}
// Determine whether to query
private boolean isSlave(String methodName) {
return methodName.startsWith("get") ||
methodName.startsWith("list") ||
methodName.startsWith("query")||
methodName.startsWith("select");
}
}
2.7 To configure SpringBoot Of applicationContext.properties Turn on MyBatis journal
logging.level.com.example=trace2.8 Create a new object entity class
package com.example.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
}
2.9 newly build mapper
package com.example.mapper;
import com.example.domain.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
@Insert("insert into t_user(name) values(#{name})")
void save(User entity);
@Select("select id,name from t_user where id = #{id}")
User selectById(Long id);
}
2.10 New interface
package com.example.service;
import com.example.domain.User;
public interface IUserService {
void save(User entity);
User selectById(Long id);
}
2.11 newly build service
package com.example.service.impl;
import com.example.domain.User;
import com.example.mapper.UserMapper;
import com.example.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
@Transactional
public void save(User entity) {
userMapper.save(entity);
}
@Override
@Transactional(readOnly = true)
public User selectById(Long id) {
return userMapper.selectById(id);
}
}
2.9 test
package com.example;
import com.example.domain.User;
import com.example.service.IUserService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class ReadWriteApplicationTests {
@Autowired
private IUserService userService;
@Test
void contextLoads() {
}
@Test
public void save(){
userService.save(new User(null," The most handsome Blogger !"));
}
@Test
public void get(){
User user = userService.selectById(1L);
System.out.print(user);
}
}
边栏推荐
- 什么是外链和内链?
- QT中foreach的使用
- Reasons for MySQL master-slave database synchronization failure
- The broadcast module code runs normally in autojs4.1.1, but an error is reported in pro7.0 (not resolved)
- Link garbled escape character
- Huawei interview question: tall and short people queue up
- 个人PC安装软件
- 一篇文章带你入门vim
- Global and Chinese market for nasal drug delivery devices 2022-2028: Research Report on technology, participants, trends, market size and share
- General paging (2)
猜你喜欢

Hisense A7 ink screen mobile phone cannot be started

实用调试技巧

QT中foreach的使用
![[wechat applet] how did the conditional rendering list render work?](/img/db/4e79279272b75759cdc8d6f31950f1.png)
[wechat applet] how did the conditional rendering list render work?

Mathematical solution of Joseph Ring

Tidb 6.0: rendre les GRT plus efficaces 丨 tidb Book Rush

The MariaDB database was found 12 hours late

Redis中的Hash设计和节省内存数据结构设计

第2章 控制结构和函数(编程题)

F1c100s self made development board debugging process
随机推荐
Redis中的SDS理解
HOOK Native API
X Book 6.89 shield unidbg calling method
Global and Chinese market of medical mass notification system 2022-2028: Research Report on technology, participants, trends, market size and share
Openssl3.0 learning 22 provider decoder
Global and Chinese markets for advanced wound care 2022-2028: Research Report on technology, participants, trends, market size and share
HOOK Native API
Use of custom MVC
Hudi record
Redis is used in Windows system
QT中foreach的使用
F1C100S自制开发板调试过程
Tri rapide, index groupé, recherche de la plus grande valeur K dans les données
Simple custom MVC optimization
Redis中的Hash设计和节省内存数据结构设计
Global and Chinese market for nasal drug delivery devices 2022-2028: Research Report on technology, participants, trends, market size and share
mysql 主从数据库同步失败的原因
通用分页(2)
编译一个无导入表的DLL
Auto.js学习笔记16:按项目保存到手机上,不用每次都保存单个js文件,方便调试和打包