大纲 前言 学习资源 ShardingSphere-Proxy 使用 垂直分库使用案例 提示
本节将演示 SpringBoot + MyBatis Plus 如何整合 ShardingSphere-JDBC,并实现 垂直分库 ,即按照业务拆分数据库,核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将读写压力分散至不同的数据库(如下图所示)。完整的案例代码可以直接从 GitHub 下载对应章节 shardingsphere-proxy-lesson-02。
准备工作 版本说明 本案例所使用的组件版本如下表所示:
组件 版本说明 JDK 11MySQL 8.0.29SpringBoot 2.7.18ShardingSphere-Proxy 5.1.1
数据库规划 本案例是在两个 MySQL 数据库上实现的,数据库的规划如下图所示:
数据库服务器 IP 端口 库的名称 表的名称 用户数据库服务器(server-user) 192.168.2.191 3301 db_usert_user订单数据库服务器(server-order) 192.168.2.191 3302 db_ordert_orderShardingSphere-Proxy 服务器 192.168.2.191 3309 sharding_db(逻辑库)t_user(逻辑表)、t_order(逻辑表)
数据库部署 1 2 3 4 5 6 7 8 9 10 docker run -d \ -p 3301:3306 \ -v /data/server/user/conf:/etc/mysql/conf.d \ -v /data/server/user/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai \ --name server-user \ --restart always \ mysql:8.0.29
更改用户数据库服务器(server-user)的默认密码校验方式 1 2 3 4 5 6 7 8 docker exec -it server-user env LANG=C.UTF-8 /bin/bash mysql -uroot -p ALTER USER 'root' @'%' IDENTIFIED WITH mysql_native_password BY '123456' ;
1 2 3 4 5 6 7 8 9 10 docker run -d \ -p 3302:3306 \ -v /data/server/order/conf:/etc/mysql/conf.d \ -v /data/server/order/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai \ --name server-order \ --restart always \ mysql:8.0.29
更改订单数据库服务器(server-order)的默认密码校验方式 1 2 3 4 5 6 7 8 docker exec -it server-order env LANG=C.UTF-8 /bin/bash mysql -uroot -p ALTER USER 'root' @'%' IDENTIFIED WITH mysql_native_password BY '123456' ;
数据库初始化 在用户数据库服务器(server-user)中,执行以下 SQL 语句: 1 2 3 4 5 6 7 8 9 10 11 12 CREATE DATABASE db_user;USE db_user; CREATE TABLE t_user ( id BIGINT AUTO_INCREMENT, uname VARCHAR (30 ), PRIMARY KEY (id) );
在订单数据库服务器(server-order)中,执行以下 SQL 语句: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 CREATE DATABASE db_order;USE db_order; CREATE TABLE t_order ( id BIGINT AUTO_INCREMENT, order_no VARCHAR (30 ), user_id BIGINT , amount DECIMAL (10 ,2 ), PRIMARY KEY(id) );
ShardingSphere-Proxy 配置 垂直分库配置 ShardingSphere-Proxy 支持两种配置模式,包括 YAML 和 DistSQL,任意选择一种即可。
YAML 模式 创建或编辑 ShardingSphere-Proxy 的 conf/config-sharding.yaml 配置文件,添加以下垂直分库的配置内容: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 schemaName: sharding_db dataSources: ds_0: url: jdbc:mysql://192.168.2.191:3301/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 ds_1: url: jdbc:mysql://192.168.2.191:3302/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 rules: - !SHARDING tables: t_user: actualDataNodes: ds_0.t_user t_order: actualDataNodes: ds_1.t_order
ShardingSphere-Proxy 垂直分库的配置内容添加完成后,需要重启 ShardingSphere-Proxy 服务(假设这里是通过 Docker 部署 ShardingSphere-Proxy 服务),否则配置不会生效 1 2 docker restart server-proxy
查看 ShardingSphere-Proxy 中的配置规则(ShardingSphere-Proxy 启动时会从 YAML 配置文件中加载) 1 2 mysql -h192 .168.2.191 -P3309 -uroot -p
1 2 3 4 5 6 7 8 USE sharding_db; SHOW SCHEMA RESOURCES;SHOW SHARDING TABLE RULES;
DistSQL 模式 远程连接 ShardingSphere-Proxy 1 mysql -h192 .168.2.191 -P3309 -uroot -p
1 2 3 4 5 CREATE DATABASE sharding_db;USE sharding_db;
1 2 3 4 5 6 7 8 9 10 11 12 13 ADD RESOURCE ds_0 ( URL= "jdbc:mysql://192.168.2.191:3301/db_user?serverTimezone=UTC&useSSL=false", USER = root, PASSWORD= 123456 , PROPERTIES( "connectionTimeoutMilliseconds"= "30000", "idleTimeoutMilliseconds"= "60000", "maxLifetimeMilliseconds"= "1800000", "maxPoolSize"= "50", "minPoolSize"= "1" ) );
1 2 3 4 5 6 7 8 9 10 11 12 13 ADD RESOURCE ds_1 ( URL= "jdbc:mysql://192.168.2.191:3302/db_order?serverTimezone=UTC&useSSL=false", USER = root, PASSWORD= 123456 , PROPERTIES( "connectionTimeoutMilliseconds"= "30000", "idleTimeoutMilliseconds"= "60000", "maxLifetimeMilliseconds"= "1800000", "maxPoolSize"= "50", "minPoolSize"= "1" ) );
1 2 3 4 CREATE SHARDING TABLE RULE t_user ( DATANODES('ds_0.t_user' ) );
1 2 3 4 CREATE SHARDING TABLE RULE t_order ( DATANODES('ds_1.t_order' ) );
查看配置规则(使用 DistSQL 定义数据源和数据分片规则后,不需要重启 ShardingSphere-Proxy 服务,默认会自动生效) 1 2 3 4 5 SHOW SCHEMA RESOURCES;SHOW SHARDING TABLE RULES;
查看日志信息 查看 ShardingSphere-Proxy 运行的实时日志信息 1 2 3 4 5 docker exec -it server-proxy env LANG=C.UTF-8 /bin/bash tail -f /opt/shardingsphere-proxy/logs/stdout.log
远程访问测试 远程连接 ShardingSphere-Proxy 1 mysql -h192 .168.2.191 -P3309 -uroot -p
1 2 3 4 5 6 7 8 9 10 mysql> show databases; + | schema_name | + | sharding_db | | mysql | | information_schema | | performance_schema | | sys | +
1 2 3 4 5 6 7 mysql> show tables; +-----------------------+------------+ | Tables_in_sharding_db | Table_type | +-----------------------+------------+ | t_user | BASE TABLE | | t_order | BASE TABLE | +-----------------------+------------+
1 mysql> select * from t_user;
1 mysql> select * from t_order;
提示
执行完上述 select 操作后,可以在 ShardingSphere-Proxy 的日志信息中,查看对应的逻辑 SQL 和真实 SQL,以此判断垂直分库是否生效。
SpringBoot 实战使用案例 添加依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <properties > <spring-boot.version > 2.7.18</spring-boot.version > <mysql-connector.version > 8.2.0</mysql-connector.version > <mybatis-plus.version > 3.3.1</mybatis-plus.version > </properties > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-dependencies</artifactId > <version > ${spring-boot.version}</version > <type > pom</type > <scope > import</scope > </dependency > </dependencies > </dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > com.mysql</groupId > <artifactId > mysql-connector-j</artifactId > <version > ${mysql-connector.version}</version > </dependency > <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > ${mybatis-plus.version}</version > </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 > <exclusions > <exclusion > <groupId > org.junit.vintage</groupId > <artifactId > junit-vintage-engine</artifactId > </exclusion > </exclusions > </dependency > </dependencies >
创建实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.Data;@TableName("t_user") @Data public class User { @TableId(type = IdType.AUTO) private Long id; private String uname; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.Data;import java.math.BigDecimal;@TableName("t_order") @Data public class Order { @TableId(type = IdType.AUTO) private Long id; private String orderNo; private Long userId; private BigDecimal amount; }
创建 Mapper 1 2 3 4 5 6 7 8 import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.clay.shardingjdbc.entity.User;import org.apache.ibatis.annotations.Mapper;@Mapper public interface UserMapper extends BaseMapper <User > {}
1 2 3 4 5 6 7 8 import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.clay.shardingjdbc.entity.Order;import org.apache.ibatis.annotations.Mapper;@Mapper public interface OrderMapper extends BaseMapper <Order > {}
配置数据源 创建配置文件(application.properties),配置数据源 1 2 3 4 5 6 7 8 9 10 11 spring.application.name =sharding-proxy-demo spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.datasource.url =jdbc:mysql://192.168.2.191:3309/sharding_db?serverTimezone=GMT%2B8&useSSL=false spring.datasource.username =root spring.datasource.password =root mybatis-plus.configuration.log-impl =org.apache.ibatis.logging.stdout.StdOutImpl
测试代码 插入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @SpringBootTest class ShardingTest { @Autowired private UserMapper userMapper; @Autowired private OrderMapper orderMapper; @Test public void testInsertOrderAndUser () { User user = new User(); user.setUname("张三" ); userMapper.insert(user); Order order = new Order(); order.setOrderNo("00001" ); order.setUserId(user.getId()); order.setAmount(new BigDecimal(100 )); orderMapper.insert(order); } }
测试代码运行后,ShardingSphere-Proxy 运行输出的日志信息如下:
1 2 3 4 5 6 7 21:31:51.924 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - Logic SQL: INSERT INTO t_user ( uname ) VALUES ( '张三' ) 21:31:51.924 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty) 21:31:51.924 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - Actual SQL: ds_0 ::: INSERT INTO t_user ( uname ) VALUES ('张三') 21:31:52.075 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - Logic SQL: INSERT INTO t_order ( order_no, user_id, amount ) VALUES ( '00001', 1, 100 ) 21:31:52.075 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty) 21:31:52.076 [ShardingSphere-Command-10] INFO ShardingSphere-SQL - Actual SQL: ds_1 ::: INSERT INTO t_order ( order_no, user_id, amount ) VALUES ('00001', 1, 100)
查询数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @SpringBootTest class ShardingTest { @Autowired private UserMapper userMapper; @Autowired private OrderMapper orderMapper; @Test public void testSelectFromOrderAndUser () { User user = userMapper.selectById(1L ); System.out.println(user); Order order = orderMapper.selectById(1L ); System.out.println(order); } }
测试代码运行后,ShardingSphere-Proxy 运行输出的日志信息如下:
1 2 3 4 5 6 7 21:39:05.122 [ShardingSphere-Command-12] INFO ShardingSphere-SQL - Logic SQL: SELECT id,uname FROM t_user WHERE id=1 21:39:05.122 [ShardingSphere-Command-12] INFO ShardingSphere-SQL - SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty) 21:39:05.122 [ShardingSphere-Command-12] INFO ShardingSphere-SQL - Actual SQL: ds_0 ::: SELECT id,uname FROM t_user WHERE id=1 21:39:05.213 [ShardingSphere-Command-13] INFO ShardingSphere-SQL - Logic SQL: SELECT id,order_no,user_id,amount FROM t_order WHERE id=1 21:39:05.213 [ShardingSphere-Command-13] INFO ShardingSphere-SQL - SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty) 21:39:05.213 [ShardingSphere-Command-13] INFO ShardingSphere-SQL - Actual SQL: ds_1 ::: SELECT id,order_no,user_id,amount FROM t_order WHERE id=1