主库: 添加、更新以及删除数据操作所使用的数据库。
从库: 查询数据操作所使用的数据库。
mysql</groupId>
mysql-connector-java</artifactId>
5.1.42</version>
</dependency>
org.mybatis.spring.boot</groupId>
mybatis-spring-boot-starter</artifactId>
1.3.1</version>
</dependency>
org.apache.shardingsphere</groupId>
sharding-jdbc-spring-boot-starter</artifactId>
4.1.1</version>
</dependency>
注:SpringBoot 依赖自行引入,本人的SpringBoot的版本是 2.3.5.RELEASE, Mybatis和Mysql版本号可自行修改
本人创建了三个测试库名称分别为test(主),test1(从),test2(从)
创建表 user
正常开发中是需要做主从同步,并且数据库不是在同一台机器上,本文只是为了测试读写分离,所以请有兴趣的同学自行去研究。
#mybatis
mybatis.mapper-locations=classpath*:mappers/*Mapper.xml
#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#自定义数据源名称
spring.shardingsphere.datasource.names=write1,read1,read2
#主库
spring.shardingsphere.datasource.write1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.write1.jdbc-url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.write1.username=root
spring.shardingsphere.datasource.write1.password=1qaz@WSX
spring.shardingsphere.datasource.write1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.write1.pool-name=hikari1
spring.shardingsphere.datasource.write1.minimum-idle=10
spring.shardingsphere.datasource.write1.maximum-pool-size=20
spring.shardingsphere.datasource.write1.idle-timeout=60000
spring.shardingsphere.datasource.write1.max-lifetime=60000
spring.shardingsphere.datasource.write1.connection-timeout=60000
spring.shardingsphere.datasource.write1.connection-test-query=SELECT 1
#从库1
spring.shardingsphere.datasource.read1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.read1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.read1.username=root
spring.shardingsphere.datasource.read1.password=1qaz@WSX
spring.shardingsphere.datasource.read1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.read1.pool-name=hikari1
spring.shardingsphere.datasource.read1.minimum-idle=10
spring.shardingsphere.datasource.read1.maximum-pool-size=20
spring.shardingsphere.datasource.read1.idle-timeout=60000
spring.shardingsphere.datasource.read1.max-lifetime=60000
spring.shardingsphere.datasource.read1.connection-timeout=60000
spring.shardingsphere.datasource.read1.connection-test-query=SELECT 1
#从库2
spring.shardingsphere.datasource.read2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.read2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.read2.username=root
spring.shardingsphere.datasource.read2.password=1qaz@WSX
spring.shardingsphere.datasource.read2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.read2.pool-name=hikari1
spring.shardingsphere.datasource.read2.minimum-idle=10
spring.shardingsphere.datasource.read2.maximum-pool-size=20
spring.shardingsphere.datasource.read2.idle-timeout=60000
spring.shardingsphere.datasource.read2.max-lifetime=60000
spring.shardingsphere.datasource.read2.connection-timeout=60000
spring.shardingsphere.datasource.read2.connection-test-query=SELECT 1
#读写分离配置(1主2从)
#注意这里的master-slave-rules.write1 要写主库数据源名称
spring.shardingsphere.sharding.master-slave-rules.write1.master-data-source-name=write1
spring.shardingsphere.sharding.master-slave-rules.write1.slave-data-source-names=read1,read2
#负载均衡(官方提供两种,轮询算法:ROUND_ROBIN,随机访问算法:RANDOM)
spring.shardingsphere.masterslave.name=ms
spring.shardingsphere.masterslave.master-data-source-name=write1
spring.shardingsphere.masterslave.slave-data-source-names=read1,read2
spring.shardingsphere.masterslave.load-balance-algorithm-type=ROUND_ROBIN
#打印sql(默认都是false)
spring.shardingsphere.props.sql.show=true
spring.shardingsphere.props.sql.detail=true
注:其他SpringBoot的配置自行配置,本部分只贴出相关配置信息
Controller
package com.example.demo.controller;
import com.example.demo.bean.User;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@RestController
package com.example.demo.controller;
import com.example.demo.bean.User;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@RestController
public class UserController {
@Resource
private UserService userService;
/**
* 根据主键获取用户信息
* @author xxf
* @date 2021/4/14 16:28
*/
@GetMapping("/user/{id}")
public User get(@PathVariable Integer id) {
return userService.get(id);
}
/**
* 获取用户列表
* @author xxf
* @date 2021/4/14 16:29
*/
@GetMapping("/userList")
public List<User> getList() {
return userService.getList();
}
/**
* 新增用户
* @author xxf
* @date 2021/4/14 16:30
*/
@PostMapping("/addUser")
public String get(@RequestBody User user) {
userService.insert(user);
return "ok";
}
}
Service
package com.example.demo.service;
import com.example.demo.bean.User;
import com.example.demo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Service
public class UserService {
@Resource
private UserMapper userMapper;
public User get(Integer id) {
log.info("【UserService】 get param:{}", id);
User user = userMapper.selectByPrimaryKey(id);
return user;
}
public List<User> getList() {
log.info("【UserService】 getList param:{}", 2);
List<User> users = userMapper.selectAll();
return users;
}
public void insert(User user) {
log.info("【UserService】 insert param:{}", user);
userMapper.insertSelective(user);
}
}
启动日志中能看到我们配置的主从数据库数据源信息和使用的负载均衡算法
往数据库里插入多条用户信息,操作多次,从日志中可以发现都是走的主库(写库write1),然后看数据库中是否有信息,发现主库中是多了两条刚才插入的数据,从库中是没有的(我是没有做主从同步的)。
通过日志发现,走的是两个从库(读库read1,read2),并且是交替访问,
因为我在配置文件中设置的负载均衡算法是ROUND_ROBIN(轮训)。
至此,通过Sharding-JDBC做数据库的读写分离已经整合完成。本文只是一个简单DEMO,有很多不规范的地方,但是配置信息是完全可以作为参照的。
其他信息可以查阅官方文档: https://shardingsphere.apache.org/document/current/cn/overview/