Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分庫分表


1 概述

本文主要講述了如何使用ShardingSphere(其中的Sharding-JDBC)和MyBatisPlus進行分庫分表,具體步驟包括:

  • 准備數據庫環境
  • 准備依賴
  • 編寫配置文件
  • 測試

2 准備數據庫環境

2.1 兩庫六表

准備好兩個庫:

  • test0
  • test1

在兩個庫中分別建立三個字段一樣的表:

  • user0
  • user1
  • user2

在這里插入圖片描述

字段如下:

在這里插入圖片描述

這樣就准備了兩個庫以及其中的六個表了。

2.2 (可選)MyBatis Plus Generator代碼生成表

因為MyBatis Plus Generator生成的Controller等代碼默認是按照表名命名的,這樣就會生成類似User0User0Controller這樣的命名,因此這里創建一個叫user的表,僅僅用於代碼的生成,里面不會存放任何的數據:

在這里插入圖片描述

3 新建項目

新建Spring Boot項目並引入如下依賴:

  • Druid
  • MyBatis Plus starter
  • MyBaits Plus Generator
  • Velocity core
  • ShardingSphere
  • Yitter(一個雪花id生成器)

Maven如下:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
    <groupId>org.realityforge.org.jetbrains.annotations</groupId>
    <artifactId>org.jetbrains.annotations</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>com.github.yitter</groupId>
    <artifactId>yitter-idgenerator</artifactId>
    <version>1.0.6</version>
</dependency>

Gradle如下:

implementation 'com.baomidou:mybatis-plus-boot-starter:3.4.3.1'
implementation 'org.apache.velocity:velocity-engine-core:2.3'
implementation 'org.realityforge.org.jetbrains.annotations:org.jetbrains.annotations:1.7.0'
implementation 'com.alibaba:druid:1.2.6'
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1'
implementation 'com.github.yitter:yitter-idgenerator:1.0.6'

4 配置文件

配置文件可以參考ShardingSphere文檔,這里給出一個示例配置:

spring:
  shardingsphere:
    datasource:
      names: test0,test1                                        # 數據源,這里為了方便直接使用庫名的名稱
      test0:                                                   
        type: com.alibaba.druid.pool.DruidDataSource            # Druid連接池
        url: jdbc:mysql://127.0.0.1:3306/test0                  # 連接test0的url
        username: root
        password: 123456
      test1:
        type: com.alibaba.druid.pool.DruidDataSource            # Druid連接池
        url: jdbc:mysql://127.0.0.1:3306/test1                  # 連接test1的url
        username: root
        password: 123456
    sharding:
      default-database-strategy:                                # 默認分庫策略
        inline:  
          sharding-column: age                                  # 表示根據age列進行分庫
          algorithm-expression: test$->{age % 2}                # 根據age對2的模進行分庫,模為0表示test0庫,模為1表示test1庫
      tables:
        user:
          actual-data-nodes: test$->{0..1}.user$->{0..2}        # 表的名字,test$->{0..1}可以表示test0、test1兩個庫
                                                                # user$->{0..2}表示user0、user1、user2三個庫
          table-strategy:                                       # 分表策略
            inline:
              sharding-column: id                               # 根據哪一列進行分表,id表示根據列名為"id"的列分表
              algorithm-expression: user$->{id%3}               # 分表規則為id對3取模,id%3為0表示分到user0表
                                                                # id%3為1表示分到user1表,id%3為2表示分到user2表
    props:
      sql:
        show:
          true                                                  # 打印sql

這里使用自動取模分片策略,ShardingShphere內置了如下分片算法:

  • 自動分片算法:取模分片、哈希取模分片、基於分片容量的范圍分片、基於分片邊界的范圍分片、自動時間段分片
  • 標准分片算法:行表達式分片、時間范圍分片
  • 復合行表達式分片
  • Hint行表達式分片

如果不能滿足需要還可以自定義分片算法,具體請看官方文檔

5 測試代碼生成

使用MyBaits Plus Generator生成相應代碼,具體使用可以參考筆者之前的文章,這里直接放上生成類的代碼:

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;

public class MyBatisPlusGenerator {
    public static void main(String[] args) {
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/test0", "root", "123456").build();
        String projectPath = System.getProperty("user.dir");
        StrategyConfig strategyConfig = new StrategyConfig.Builder().addInclude("user").build();
        GlobalConfig globalConfig = new GlobalConfig.Builder().outputDir(projectPath + "/src/main/java").openDir(false).build();
        PackageConfig packageConfig = new PackageConfig.Builder().moduleName("user").parent("com.example.demo").serviceImpl("service").build();
        new AutoGenerator(dataSourceConfig).global(globalConfig).packageInfo(packageConfig).strategy(strategyConfig).execute();
    }
}

UserController類修改如下:

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserController {
    private final Random random = new Random();
    private final UserServiceImpl service;
    @GetMapping("/select")
    public List<User> select(){
        return service.list();
    }

    @GetMapping("/insert")
    public boolean insert(){
        return service.save(User.builder().age(random.nextInt(80)+20).name("test name").email("test@test.com").build());
    }
}

6 增加雪花id生成器

首先修改User類,增加一個@Builder注解,同時修改id的生成策略,使用IdType.ASSIGN_ID

@Builder
public class User implements Serializable {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    //...
}

新建id生成器類:

import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class IdGenerator implements IdentifierGenerator {
    final IdGeneratorOptions options = new IdGeneratorOptions((short) 1);

    @PostConstruct
    public void init() {
        YitIdHelper.setIdGenerator(options);
    }

    @Override
    public Long nextId(Object entity) {
        return YitIdHelper.nextId();
    }
}

這樣生成id的時候,就會自動調用nextId()方法,其中的id生成器可以根據需要進行替換,換成其他雪花id生成器或分布式id生成器。

配置的時候可以參考MyBaits Plus 自定義ID生成器文檔

7 測試

先隨機插入三條數據,刷新三次如下頁面:

localhost:8080/test/user/insert

在這里插入圖片描述

可以看到執行了三次插入操作,插入的三個表分別是:

  • test0.user2
  • test0.user0
  • test0.user2

因為這里測試的時候年齡都恰好是偶數,都插入到了test0表。

查看數據:

http://localhost:8080/user/select

在這里插入圖片描述

日志輸出如下:

在這里插入圖片描述

表示這是對六個表查詢的結果,並將最后的結果進行聚合返回。

8 參考源碼

Java版:

Kotlin版:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM