自由的羽毛 发表于 2023-8-11 08:54:58

SpringBoot3分库分表

标签:ShardingSphere5.分库.分表;
一、简介

分库分表的设计和实现方式,在之前的内容中总结过很多,本文基于SpringBoot3和ShardingSphere5框架实现数据分库分表的能力;
不得不提ShardingSphere5文档中描述的两个基本概念:
https://img2023.cnblogs.com/blog/1691717/202308/1691717-20230810223457889-963165329.png
垂直分片
按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。
水平分片
水平分片又称为横向拆分。 相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。
下面从案例实践中,看看ShardingSphere5框架是如何实现分库分表的原理;
二、工程搭建

1、工程结构

https://img2023.cnblogs.com/blog/1691717/202308/1691717-20230810223502733-847102565.png
2、依赖管理

这里只看两个核心组件的依赖:shardingsphere-jdbc组件是5.2.1版本,mybatis组件是3.5.13版本,在依赖管理中还涉及MySQL和分页等,并且需要添加很多排除配置,具体见源码;
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis.version}</version>
</dependency>


<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>三、配置详解

1、配置文件

此处只展示分库分表的相关配值,默认数据源使用db_master库,注意tb_order库表路由的策略和分片算法的关联关系,其他工程配置详见源码仓库;
spring:
# 分库分表配置
shardingsphere:
    datasource:
      # 默认数据源
      sharding:
      default-data-source-name: db_master
      names: db_master,db_0,db_1
      db_master:
      type: com.zaxxer.hikari.HikariDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/shard_db
      username: root
      password: 123456
      db_0:
      type: com.zaxxer.hikari.HikariDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/shard_db_0
      username: root
      password: 123456
      db_1:
      type: com.zaxxer.hikari.HikariDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/shard_db_1
      username: root
      password: 123456
    rules:
      sharding:
      tables:
          # tb_order逻辑
          tb_order:
            actual-data-nodes: db_${0..1}.tb_order_${0..2}
            # tb_order库路由
            database-strategy:
            standard:
                sharding-column: order_id
                sharding-algorithm-name: database_inline
            # tb_order表路由
            table-strategy:
            standard:
                sharding-column: order_id
                sharding-algorithm-name: table_inline
      sharding-algorithms:
          # tb_order库路由算法
          database_inline:
            type: INLINE
            props:
            algorithm-expression: db_${order_id % 2}
          # tb_order表路由算法
          table_inline:
            type: INLINE
            props:
            algorithm-expression: tb_order_${order_id % 3}
    props:
      sql-show: true
      sql-comment-parse-enabled: true2、配置原理

在配置中需要管理三个数据源,shard_db默认库,在操作不涉及需要路由的表时默认使用该数据源,shard_db_0和shard_db_1是tb_order逻辑表的路由库;
https://img2023.cnblogs.com/blog/1691717/202308/1691717-20230810223507824-891612061.png
逻辑表tb_order整体使用两个数据库,每个库建3张结构相同相同的表,在操作tb_order数据时,会根据order_id字段值定位数据所属的分片节点;

[*]库路由db_${0..1}采用db_${order_id%2}的算法;
[*]表路由tb_order_${0..2}采用tb_order_${order_id%3}的算法;
四、测试案例

1、主库操作

基于Mybatis持久层框架,实现对shard_db默认库的数据操作,注意控制台的日志打印,可以看到一系列解析逻辑以及库表节点的定位,分页查询使用PageHelper组件即可;
public class MasterTest {
    @Autowired
    private BuyerMapper buyerMapper ;
    @Autowired
    private SellerMapper sellerMapper ;
    @Test
    public void testBuyerQuery (){
      // 主键查询
      Buyer buyer = buyerMapper.selectByPrimaryKey(1) ;
      System.out.println(buyer.getId()+";"+buyer.getBuyerName());
    }
    @Test
    public void testBuyerInsert (){
      // 新增数据
      Buyer buyer = new Buyer() ;
      buyer.setBuyerName("买家Three");
      System.out.println(buyerMapper.insert(buyer));
    }
    @Test
    public void testBuyerUpdate (){
      // 更新数据
      Buyer buyer = buyerMapper.selectByPrimaryKey(3) ;
      if (buyer != null){
            buyer.setBuyerName("Three买家");
            System.out.println(buyerMapper.updateByPrimaryKey(buyer));
      }
    }
    @Test
    public void testSellerPage (){
      // 1、设置分页和查询条件
      PageHelper.startPage(2,2) ;
      SellerExample sellerExample = new SellerExample() ;
      sellerExample.setOrderByClause("id asc");
      // 2、查询数据
      List<Seller> sellerList = sellerMapper.selectByExample(sellerExample) ;
      // 3、构建分页实体对象
      PageInfo<Seller> pageInfo = new PageInfo<>(sellerList) ;
      System.out.println(pageInfo);
    }
}2、分库操作

在对tb_order表执行增删改查时,会根据order_id的字段值计算库表的路由节点,注意分页时会查询所有的分库和分表,然后汇总查询的结果;
public class ShardTest {    @Autowired    private OrderMapper orderMapper ;    /**   * 写入100条数据   */    @Test    public void testOrderInsert (){      for (int i=1 ; i
页: [1]
查看完整版本: SpringBoot3分库分表