分表分库-Sharding-JDBC-入门案例
1、需求描述
使用Sharding-JDBC实现电商平台的商品列表展示,每个列表项中除了包含商品基本信息、商品描述信 息之外,还包括了商品所属的店铺信息,如下所示:
2、开发环境
- 数据库:MySQL-5.7.25
- JDK:1.8.0_201
- 应用框架:spring-boot-2.1.3.RELEASE,Mybatis 3.5.0
- Sharding-JDBC:sharding-jdbc-spring-boot-starter-4.0.0-RC1
3、数据库设计
商品与店铺信息之间进行了垂直分库,拆分为了PRODUCT_DB(商品库)和STORE_DB(店铺库);商品信 息还进行了垂直分表,拆分为了商品基本信息(store_info)和商品描述信息(product_info):
考虑到商品信息的数据增长性,对PRODUCT_DB(商品库)进行了水平分库,分片键使用店铺id,分片策 略为店铺ID%2 + 1,对商品基本信息(product_info)和商品描述信息(product_descript)进行水平分表, 分片键使用商品id,分片策略为商品ID%2 + 1,并将这两个表设置为绑定表。为避免主键冲突,ID生成策 略采用雪花算法来生成全局唯一ID,雪花算法类似于UUID,但是它能生成有序的ID,有利于提高数据 库性能。最终数据库设计如下图所示:
4、搭建数据库环境--MySQL主从同步
https://www.cnblogs.com/mangoubiubiu/p/15781092.html
5、初始化数据库
登录并连接主库,然后执行如下脚本:
- 1. 执行store_db.sql创建store数据库和store_info表
- 2. 执行product_db_1.sql创建product_db_1数据库和其中的四张表
- 3. 执行product_db_2.sql创建product_db_2数据库和其中的四张表
此时观察从库,我们会发现从库中已经存在上述数据库和表,说明主从数据同步已经发挥了作用。
store_db.sql
DROP DATABASE IF EXISTS `store_db`; CREATE DATABASE `store_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; USE `store_db`; DROP TABLE IF EXISTS `store_info`; CREATE TABLE `store_info` ( `id` BIGINT(20) NOT NULL COMMENT 'id', `store_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '店铺名称', `reputation` INT(11) NULL DEFAULT NULL COMMENT '信誉等级', `region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '店铺所在地', PRIMARY KEY (`id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; INSERT INTO `store_info` VALUES (1, '黑马铺子', 4, '110100'); INSERT INTO `store_info` VALUES (2, '黑马超市', 3, '410100');
product_db_1.sql
DROP DATABASE IF EXISTS `product_db_1`; CREATE DATABASE `product_db_1` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; USE `product_db_1`; DROP TABLE IF EXISTS `product_descript_1`; CREATE TABLE `product_descript_1` ( `id` BIGINT(20) NOT NULL COMMENT 'id', `product_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属商品id', `descript` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', PRIMARY KEY (`id`) USING BTREE, INDEX `FK_Reference_2`(`product_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_descript_2`; CREATE TABLE `product_descript_2` ( `id` BIGINT(20) NOT NULL COMMENT 'id', `product_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属商品id', `descript` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', INDEX `FK_Reference_2`(`product_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_info_1`; CREATE TABLE `product_info_1` ( `product_info_id` BIGINT(20) NOT NULL COMMENT 'id', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', `product_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称', `spec` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规格', `region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产地', `price` DECIMAL(10, 0) NULL DEFAULT NULL COMMENT '商品价格', `image_url` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品图片', PRIMARY KEY (`product_info_id`) USING BTREE, INDEX `FK_Reference_1`(`store_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_info_2`; CREATE TABLE `product_info_2` ( `product_info_id` BIGINT(20) NOT NULL COMMENT 'id', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', `product_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称', `spec` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规格', `region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产地', `price` DECIMAL(10, 0) NULL DEFAULT NULL COMMENT '商品价格', `image_url` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品图片', PRIMARY KEY (`product_info_id`) USING BTREE, INDEX `FK_Reference_1`(`store_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
product_db_2.sql
DROP DATABASE IF EXISTS `product_db_2`; CREATE DATABASE `product_db_2` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; USE `product_db_2`; DROP TABLE IF EXISTS `product_descript_1`; CREATE TABLE `product_descript_1` ( `id` BIGINT(20) NOT NULL COMMENT 'id', `product_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属商品id', `descript` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', PRIMARY KEY (`id`) USING BTREE, INDEX `FK_Reference_2`(`product_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_descript_2`; CREATE TABLE `product_descript_2` ( `id` BIGINT(20) NOT NULL COMMENT 'id', `product_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属商品id', `descript` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '商品描述', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', INDEX `FK_Reference_2`(`product_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_info_1`; CREATE TABLE `product_info_1` ( `product_info_id` BIGINT(20) NOT NULL COMMENT 'id', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', `product_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称', `spec` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规格', `region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产地', `price` DECIMAL(10, 0) NULL DEFAULT NULL COMMENT '商品价格', `image_url` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品图片', PRIMARY KEY (`product_info_id`) USING BTREE, INDEX `FK_Reference_1`(`store_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; DROP TABLE IF EXISTS `product_info_2`; CREATE TABLE `product_info_2` ( `product_info_id` BIGINT(20) NOT NULL COMMENT 'id', `store_info_id` BIGINT(20) NULL DEFAULT NULL COMMENT '所属店铺id', `product_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称', `spec` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规格', `region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产地', `price` DECIMAL(10, 0) NULL DEFAULT NULL COMMENT '商品价格', `image_url` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品图片', PRIMARY KEY (`product_info_id`) USING BTREE, INDEX `FK_Reference_1`(`store_info_id`) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
6 功能实现
一、parent 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.itheima.dbsharding</groupId> <artifactId>dbsharding</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>sharding-jdbc-demo</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> </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> <dependencyManagement> <dependencies> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.0</version> </dependency> <dependency> <groupId>javax.interceptor</groupId> <artifactId>javax.interceptor-api</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-typehandlers-jsr310</artifactId> <version>1.0.2</version> </dependency> </dependencies> </dependencyManagement> <build> <finalName>${project.name}</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*</include> </includes> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>utf-8</encoding> <useDefaultDelimiters>true</useDefaultDelimiters> </configuration> </plugin> </plugins> </build> </project>
二、children 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"> <parent> <artifactId>dbsharding</artifactId> <groupId>com.itheima.dbsharding</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>sharding-jdbc-demo</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> </dependency> </dependencies> </project>
三、配置文件
server.port=56081 spring.application.name = sharding-jdbc-demo server.servlet.context-path = /sharding-jdbc-demo spring.http.encoding.enabled = true spring.http.encoding.charset = UTF-8 spring.http.encoding.force = true # 开启swagger swagger.enable = true # 同名bean允许覆盖 spring.main.allow-bean-definition-overriding=true # 将带有下划线的表字段映射为驼峰格式的实体类属性 mybatis.configuration.map-underscore-to-camel-case = true # 定义真实数据源(6个) spring.shardingsphere.datasource.names = m0,m1,m2,s0,s1,s2 spring.shardingsphere.datasource.m0.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m0.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.m0.url = jdbc:mysql://192.168.56.13:3307/store_db?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.m0.username = root spring.shardingsphere.datasource.m0.password = root spring.shardingsphere.datasource.m1.type =com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.m1.url = jdbc:mysql://192.168.56.13:3307/product_db_1?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.m1.username = root spring.shardingsphere.datasource.m1.password = root spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.m2.url = jdbc:mysql://192.168.56.13:3307/product_db_2?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.m2.username = root spring.shardingsphere.datasource.m2.password = root spring.shardingsphere.datasource.s0.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s0.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.s0.url = jdbc:mysql://192.168.56.13:3308/store_db?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.s0.username = root spring.shardingsphere.datasource.s0.password = root spring.shardingsphere.datasource.s1.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s1.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.s1.url = jdbc:mysql://192.168.56.13:3308/product_db_1?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.s1.username = root spring.shardingsphere.datasource.s1.password = root spring.shardingsphere.datasource.s2.type = com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s2.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.s2.url = jdbc:mysql://192.168.56.13:3308/product_db_2?useUnicode=true&characterEncoding=utf8 spring.shardingsphere.datasource.s2.username = root spring.shardingsphere.datasource.s2.password = root # 定义逻辑数据源(主从对应关系) spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=s0 spring.shardingsphere.sharding.master-slave-rules.ds1.master-data-source-name=m1 spring.shardingsphere.sharding.master-slave-rules.ds1.slave-data-source-names=s1 spring.shardingsphere.sharding.master-slave-rules.ds2.master-data-source-name=m2 spring.shardingsphere.sharding.master-slave-rules.ds2.slave-data-source-names=s2 # 分库策略 spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column = store_info_id spring.shardingsphere.sharding.default-database-strategy.inline.algorithmexpression = ds$->{store_info_id % 2+1} # 分表策略 3张表 # store_info分表策略,固定分配至ds0的store_info真实表 spring.shardingsphere.sharding.tables.store_info.actual-data-nodes = ds$->{0}.store_info spring.shardingsphere.sharding.tables.store_info.table-strategy.inline.sharding-column= id spring.shardingsphere.sharding.tables.store_info.table-strategy.inline.algorithm-expression=store_info # product_info分表策略,分布在ds1,ds2的product_info_1和product_info_2表 ,分片策略为product_info_id % 2+1,product_info_id采用雪花算法 spring.shardingsphere.sharding.tables.product_info.actual-data-nodes = ds$->{1..2}.product_info_$->{1..2} spring.shardingsphere.sharding.tables.product_info.table-strategy.inline.sharding-column= product_info_id spring.shardingsphere.sharding.tables.product_info.table-strategy.inline.algorithm-expression = product_info_$->{product_info_id % 2+1} spring.shardingsphere.sharding.tables.product_info.key-generator.column=product_info_id spring.shardingsphere.sharding.tables.product_info.key-generator.type=SNOWFLAKE # product_descript分表策略,分布在ds1,ds2的product_descript_1和product_descript_2表,分片策略为product_info_id % 2+1,id采用雪花算法 spring.shardingsphere.sharding.tables.product_descript.actual-data-nodes = ds$->{1..2}.product_descript_$->{1..2} spring.shardingsphere.sharding.tables.product_descript.table-strategy.inline.sharding-column = product_info_id spring.shardingsphere.sharding.tables.product_descript.table-strategy.inline.algorithm-expression = product_descript_$->{product_info_id %2+1} spring.shardingsphere.sharding.tables.product_descript.key-generator.type=SNOWFLAKE spring.shardingsphere.sharding.tables.product_descript.key-generator.column=id # 设置绑定表 spring.shardingsphere.sharding.binding-tables = product_info,product_descript # 打开sql输出日志 spring.shardingsphere.props.sql.show = true
7 配置文件详解
一、基础配置
二、Sharding-JDBC相关配置
# 定义真实数据源(6个)
# 定义逻辑数据源(主从对应关系)
#从库的s0从主的m0同步数据
# 分库策略
# 分表策略 3张表
# store_info分表策略,固定分配至ds0的store_info真实表
# product_descript分表策略,分布在ds1,ds2的product_descript_1和product_descript_2表,分片策略为product_info_id % 2+1,id采用雪花算法 和上面一样
# 设置绑定表
三、相关增删改
java 代码 和之前用mybatis 时候一样
实际表有后缀
只写配置文件绑定的逻辑表就完事了
四、总结
使用Sharding-JDBC关键全在配置文件 ,实际代码和之前 用单表时的差不多