前言
本文章基于Shardingsphere做简单的读写分离, 分库分表, 提供初学者了解Shardingsphere.
步骤
- SQL 准备, ds0,ds1作为主库, ds0_slave0,ds0_slave1, ds1_slave0,ds1_slave1 作为从库,sql如下:
create database ds0;
create database ds0_slave0;
create database ds0_slave1;
create database ds1;
create database ds1_slave1;
create database ds1_slave1;
-- id bigint(20) not null comment 'id',
-- name varchar(25) not null comment '名称',
-- age int(4) not null comment '年龄',
create table ds0.t_order_0 ();
create table ds0.t_order_2 ();
create table ds0.t_order_4 ();
create table ds0_slave0.t_order_0 ();
create table ds0_slave0.t_order_2 ();
create table ds0_slave0.t_order_4 ();
create table ds0_slave1.t_order_0 ();
create table ds0_slave1.t_order_2 ();
create table ds0_slave1.t_order_4 ();
create table ds1.t_order_1 ();
create table ds1.t_order_3 ();
create table ds1.t_order_5 ();
create table ds1_slave0.t_order_1 ();
create table ds1_slave0.t_order_3 ();
create table ds1_slave0.t_order_5 ();
create table ds1_slave1.t_order_1 ();
create table ds1_slave1.t_order_3 ();
create table ds1_slave1.t_order_5 ();
- 新建maven项目, 导入jar包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<!-- mybatisplus相关Jar -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 保证 Spring AOP 相关的依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<!-- freemarker 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
- 自动生成CRUD代码
package com.sharding.shardingtest.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(value = "t_order")
public class Order implements Serializable {
@TableId(value = "id", type = IdType.NONE)
private Long id;
/**
* 名称
*/
private String name;
/**
* 年龄
*/
private Integer age;
}
- Shardingsphere配置文件 application-sharding-master-slave.yml
spring:
shardingsphere:
datasource:
names: ds0,ds1,slave0,slave1,slave2,slave3
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/ds0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/ds1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
slave0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0_slave0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
slave1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0_slave1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
slave2:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds1_slave0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
slave3:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds1_slave1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
sharding:
binding-tables: t_order
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: ds_$->{id % 2}
tables:
t_order:
actual-data-nodes: ds_0.t_order_$->{[0,2,4]}, ds_1.t_order_$->{[1,3,5]}
table-strategy:
inline:
sharding-column: id
algorithm-expression: t_order_$->{id % 6}
key-generator:
column: id
type: SNOWFLAKE
props:
worker:
id: 123
master-slave-rules: # 读写分离配置
ds_0:
master-data-source-name: ds0
slave-data-source-names:
- slave0
- slave1
loadBalanceAlgorithmType: Random
ds_1:
master-data-source-name: ds1
slave-data-source-names:
- slave2
- slave3
loadBalanceAlgorithmType: ROUND_ROBIN
props:
sql:
show: true # 打印 SQL
# acceptor:
# size: # accept连接的线程数量,默认为cpu核数2倍
# executor:
# size: #工作线程数量最大,默认值: 无限制
# max:
# connections:
# size:
# per:
# query: # 每个查询可以打开的最大连接数量,默认为1
# proxy:
# frontend:
# flush:
# threshold: # proxy的服务时候,对于单个大查询,每多少个网络包返回一次
# transaction:
# type: # 默认LOCAL,proxy的事务模型 允许LOCAL,XA,BASE三个值 LOCAL无分布式事务,XA则是采用atomikos实现的分布式事务 BASE目前尚未实现
# opentracing:
# enabled: # 是否启用opentracing
# backend:
# use:
# nio: # 是否采用netty的NIO机制连接后端数据库,默认False ,使用epoll机制
# max:
# connections: # 使用NIO而非epoll的话,proxy后台连接每个netty客户端允许的最大连接数量(注意不是数据库连接限制) 默认为8
# connection:
# timeout:
# seconds: #使用nio而非epoll的话,proxy后台连接的超时时间,默认60s
# check:
# table:
# metadata:
# enabled: #是否在启动时检查分表元数据一致性,默认值: false
- application.yml 配置
spring:
profiles:
active: sharding-master-slave
# include: orchestration-zookeeper
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
typeAliasesPackage: com.sharding.shardingtest.entity
configuration:
map-underscore-to-camel-case: true
global-config:
id-type: NONE
field-strategy: NOT_EMPTY
db-column-underline: true
refresh-mapper: true
#capital-mode: true
#key-generator: com.baomidou.springboot.xxx
# logic-delete-value: 1
# logic-not-delete-value: 0
#meta-object-handler: com.baomidou.springboot.xxx
#sql-injector: com.baomidou.springboot.xxx
- 单元测试
package com.sharding.shardingtest;
import com.sharding.shardingtest.api.IOrderService;
import com.sharding.shardingtest.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class ShardingTestApplicationTests {
@Resource
IOrderService orderService;
@Test
public void contextLoads() {
for (int i = 0 ;i < 10;i++){
Order order = new Order();
order.setAge(new Random().nextInt(100));
order.setName("第" + order.getAge());
orderService.save(order);
}
// Long id = 1628732873341222914L;
// Order order = orderService.getById(id);
// log.info("order: {}", order == null);
}
}
- 观察数据
已经实现分库分表功能!!!