案例:SpringBoot集成Sharding-JDBC实现分表分库与主从同步(详细版)

案例:SpringBoot集成Sharding-JDBC实现分表分库与主从同步:详细版

  • 1. 案例分析
  • 2. 主从同步
    • 2.1 主从数据库准备
    • 2.2 简单插点数据
  • 3 案例代码
    • 3.1 application.properties配置信息
    • 3.2 测试
  • 4. 遇到的坑
    • 4.1 水平分表时的属性设置
    • 4.2 绑定表的配置

1. 案例分析

表结构:
在这里插入图片描述
垂直分库:STORE_DBPRODUCT_DB
垂直分表:商品表分为:商品信息与商品描述表
水平分库:PRODUCT_DB分为PRODUCT_DB_1PRODUCT_DB_2
水平分表:商品信息与商品描述表1和商品信息与商品描述表2

在这里插入图片描述

2. 主从同步

2.1 主从数据库准备

在这里插入图片描述

主库与从库保持一致,本文案例主要涉及到三个数据库:store_dbproduct_db_1product_db_2

在这里插入图片描述

具体MySQL的主从同步配置,请看我之前的文章。Mysql8.0以上的版本实现主从同步

数据库store_db中的表创建:

DROP TABLE IF EXISTS `region`;
CREATE TABLE `region` (
`id` BIGINT(20) NOT NULL COMMENT 'id',
`region_code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT
'地理区域编码',
`region_name` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '地理区域名称',
`level` TINYINT(1) NULL DEFAULT NULL COMMENT '地理区域级别(省、市、县)',
`parent_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;DROP TABLE IF EXISTS `store_info`;CREATE TABLE `store_info` (`id` bigint NOT NULL COMMENT 'id',`store_name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '店铺名称',`reputation` int DEFAULT NULL COMMENT '信誉等级',`region_code` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '店铺所在地',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;

product_db_1product_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',
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_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;

2.2 简单插点数据

INSERT INTO `region` VALUES (1, '110000', '北京', 0, NULL);
INSERT INTO `region` VALUES (2, '410000', '河南省', 0, NULL);
INSERT INTO `region` VALUES (3, '110100', '北京市', 1, '110000');
INSERT INTO `region` VALUES (4, '410100', '郑州市', 1, '410000');

这里只向region表中插入数据,其他表测试时在搞

3 案例代码

3.1 application.properties配置信息

# Server port
server.port=8080# Spring Boot 应用属性配置
spring.main.allow-bean-definition-overriding=true
spring.application.name=sharding-jdbc-test-04# ShardingSphere 数据源配置,总共对应六个主库:m0,m1,m2;从库:s0,s1,s2
spring.shardingsphere.datasource.names=m0,m1,m2,s0,s1,s2#配置m0连接
spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/store_db?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=root#配置s0连接
spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.s0.url=jdbc:mysql://localhost:3307/store_db?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.s0.username=root
spring.shardingsphere.datasource.s0.password=root#配置m1连接
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/product_db_1?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=root#配置s1连接
spring.shardingsphere.datasource.s1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.s1.url=jdbc:mysql://localhost:3307/product_db_1?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.s1.username=root
spring.shardingsphere.datasource.s1.password=root#配置m2连接
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/product_db_2?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=root#配置s2连接
spring.shardingsphere.datasource.s2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.s2.url=jdbc:mysql://localhost:3307/product_db_2?useUnicode=true&characterEncoding=utf8&useSSL=false
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# 设计数据库的分片键:store_info_id以及分片算法,根据{store_info_id%2 +1}可以计算机目标数据库名称
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=store_info_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{store_info_id%2 +1}#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:水平分表设计
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:水平分表设计
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.column=id
spring.shardingsphere.sharding.tables.product_descript.key-generator.type=SNOWFLAKE# 绑定关联表:product_info,product_descript
spring.shardingsphere.sharding.binding-tables[0]=product_info,product_descript#指定广播表region
spring.shardingsphere.sharding.broadcast-tables=region# 添加日志
spring.shardingsphere.props.sql.show=true# MyBatis configuration
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.type-aliases-package=com.rql.entity

3.2 测试

在这里插入图片描述

按照数据库表创建各个实体类:
其中ProductInfo是一个模型类,关联了其他表的属性:

package com.rql.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductInfo {private Long productInfoId;private Long storeInfoId;private String productName;private String spec;private String regionCode;private BigDecimal price;private String imageUrl;//关联信息private String descript;private String storeName;private int reputation;private String storeRegionName;private String placeOfOrigin;}

Dao层:

@Mapper
@Component
public interface ProductDao {//添加商品基本信息@Insert("insert into product_info(store_info_id,product_name,spec,region_code,price)values (#{storeInfoId},#{productName},#{spec},#{regionCode},#{price})")@Options(useGeneratedKeys = true,keyProperty = "productInfoId",keyColumn = "product_info_id")int insertProductInfo(ProductInfo productInfo);//添加商品描述信息@Insert("insert into product_descript(product_info_id,descript,store_info_id) values (#{productInfoId},#{descript},#{storeInfoId})")@Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id")int insertProductDescript(ProductDescript productDescript);//分页查询@Select("select i.*,d.descript,r.region_name placeOfOrigin from product_info i join product_descript d on i.product_info_id=d.product_info_id join region r on i.region_code=r.region_code order by product_info_id desc limit #{start},#{pageSize}")List<ProductInfo> selectProductList(@Param("start")int start,@Param("pageSize") int pageSize);//商品总数@Select("select count(1) from product_info")int selectCount();//商品分组统计@Select("select t.region_code,count(1) as num from product_info t group by t.region_code having num>1 order by region_code")List<Map> selectProductGroupList();
}

直接在测试类中测试:


@SpringBootTest(classes = SpringBootApplication.class)
@RunWith(SpringRunner.class)
public class ShardingTest {@AutowiredProductService productService;@AutowiredProductDao productDao;@Testpublic void testCreateProduct() {for (int i = 0; i < 10; i++) {ProductInfo productInfo = new ProductInfo();productInfo.setStoreInfoId(1L);productInfo.setProductName("Java编程思想"+i);productInfo.setSpec("大号"+i);productInfo.setPrice(new BigDecimal(i));productInfo.setRegionCode("410100");productInfo.setDescript("Java编程思想不错"+i);productService.createProduct(productInfo);}}//查询商品@Testpublic void testQueryProduct() {List<ProductInfo> productInfoList = productService.queryProduct(1,10);System.out.println(productInfoList);}//统计商品总数@Testpublic void testSelectCount(){System.out.println(productDao.selectCount());}//商品分组统计@Testpublic void testSelectProductGroupList(){System.out.println(productDao.selectProductGroupList());}
}

4. 遇到的坑

4.1 水平分表时的属性设置

之前我是这样设置的:

spring.shardingsphere.sharding.tables.default.database-strategy.inline.sharding-column=store_info_id
spring.shardingsphere.sharding.tables.default.database-strategy.inline.algorithm-expression=ds$->{store_info_id%2 +1}

结果发现在插入数据时,m1m2数据源均执行了插入过程,而我的目的是根据store_info_id设置的为1,正确的过程应该是只在m2的表中插入数据才对。

解决:原来问题出现在配置的属性上,下面是修改后的属性配置,就成功地解决了上面的问题

spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=store_info_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{store_info_id%2 +1}

可以发现不同在于default.database-strategy改为了default-database-strategy,很明显第一种是不符合Sharding-JDBC的规范的。这种小细节有时候很难发现。

4.2 绑定表的配置

我之前是这样配置的:

spring.shardingsphere.sharding.binding-tables=product_info,product_descript

在进行关联查询时,就会以笛卡尔积的形式去查,这明显是不对的,因此修改后的配置如下:

spring.shardingsphere.sharding.binding-tables[0]=product_info,product_descript

如果还想继续添加绑定,则就继续增加数据即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/644093.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SCSS全局配置 vue项目(二)

目录 1、先要查看node版本 2、安装对应的node-sass、sass-loader版本 2.1根据项目使用的node版本安装对应的node-sass版本 2.2根据node-sass版本选择兼容的sass-loader版本&#xff0c;不然项目无法正常运行 3、在 vue.config.js 中配置&#xff1a; 4、在组件中…

CSS的网页美化功能

<1>文字类 通常情况下&#xff0c;一般使用span对文字进行重点突出&#xff0c;用div来操作一段代码块。 字体的所有属性&#xff1a; 属性描述font在一个声明中设置所有的字体属性font-family指定文本的字体系列font-size指定文本的字体大小font-style指定文本的字体样…

异地组网、内部网络需求同时满足,贝锐企业路由器G300开箱体验

由于公司最近新增了办事处&#xff0c;作为IT管理员的我不仅需要搞定办事处的网络&#xff0c;还需要解决远程访问公司内部办公系统以及文件存储服务器的问题。 在此之前&#xff0c;只有少量人员出差时&#xff0c;我们采用了虚拟专网方案来进行远程访问。然而&#xff0c;新…

gcc/g++ 的使用

————gcc&#xff1a;只能编译c语言 ————g&#xff1a;c和c都可以编译 当然&#xff0c;c语言编译还是推荐gcc。 在学习gcc/g之前&#xff0c;我们要先了解一些知识点&#xff1a; 一、背景知识 1&#xff0c;预处理 gcc -E就是告诉编译器到预处理阶段就停下来&am…

jvm中的引用类型

Java中的引用类型 1.强引用 一个对象A被局部变量、静态变量引用了就产生了强引用。因为局部变量、静态变量都是被GC Root对象关联上的&#xff0c;所以被引用的对象A&#xff0c;就在GC Root的引用链上了。只要这一层关系存在&#xff0c;对象A就不会被垃圾回收器回收。所以只要…

MySQL简解

文章目录 1. MySQL框架2. 执行流程2.1. 连接池&#xff1a;2.2. SQL 前端(SEVER)2.2.0. 查询缓存2.2.1. SQL 接口2.2.2. SQL 解析器2.2.3. SQL 执行器2.2.4. INNODB 中读写操作 2.3. 数据的保存形式 3.其他重要概念3.1. 索引3.1.1. 简单概念3.1.2. 索引优化&#xff1a;1. Usin…

Node.js -- HTTP协议和网络基础概念

文章目录 1. 初识HTTP协议2. 窥探HTTP协议2.1 请求报文结构2.2 响应报文 3. 网络基础概念3.1 IP3.2 端口 本节相关内容都可以在 添加链接描述进行查看&#xff0c;深入了解相关内容。 1. 初识HTTP协议 HTTP协议其实就是浏览器和服务器之间的一个协议&#xff0c;浏览器会向服务…

相亲平台app小程序

相亲平台app小程序是一种基于手机应用的微型程序&#xff0c;专为在线相亲交友活动设计。它提供了一系列的功能&#xff0c;旨在帮助用户更方便、更高效地找到心仪的伴侣。 首先&#xff0c;用户可以在个人资料部分上传照片、填写个人资料、设置兴趣爱好等信息&#xff0c;以便…

【Git教程】(十五)二分法排错 — 概述及使用要求,执行过程及其实现(用二分法人工排错或自动排错),替代解决方案 ~

Git教程 二分法排错 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 用二分法人工排错3.2 用二分法自动排错 4️⃣ 替代解决方案 在开发过程中&#xff0c;我们经常会突然遇到一个错误&#xff0c;是之前早期版本在成功通过测试时没有出现过的。这时候&#xff0c;时下较…

基于spring boot学生综合测评系统

基于spring boot学生综合测评系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件…

主打国产算力 广州市通用人工智能公共算力中心项目签约

4月9日&#xff0c;第十届广州国际投资年会期间&#xff0c;企商在线&#xff08;北京&#xff09;数据技术股份有限公司与广州市增城区政府就“广州市通用人工智能公共算力中心”项目进行签约。 该项目由广州市增城区人民政府发起&#xff0c;企商在线承建。项目拟建成中国最…

程序员过了35岁没人要?“这行越老越香”

程序员35岁失业&#xff1f;参加完OceanBase开发者大会&#xff0c;我又悟了&#xff01; 周六参加了OceanBase2024 开发者大会的现场&#xff0c;来之前我其实挺忐忑的&#xff0c;我觉得一个数据库产品的发布会&#xff0c;能有什么新鲜的东西&#xff1f; 踏入酒店的那一刻&…