天天看點

Spring Boot demo系列(十四):ShardingSphere + MyBatisPlus 分庫分表 + 讀寫分離1 概述2 環境3 資料庫環境準備4 建立項目5 配置檔案6 準備測試代碼7 測試8 參考代碼

1 概述

之前筆者寫過兩篇文章:

  • ShardingSphere 讀寫分離
  • ShardingSphere 分庫分表

這裡将兩者結合起來,實作讀寫分離+分庫分表的功能。關于環境的配置本文将進行簡化叙述,詳細可以參考前兩篇文章。

2 環境

  • MySQL 8.0.25

    Docker

  • MyBatis Plus 3.4.3.1

  • MyBatis Plus Generator 3.5.0

  • Druid 1.2.6

  • ShardingSphere 4.1.1

  • Yitter 1.0.6

    (一個雪花

    id

    生成器)

3 資料庫環境準備

由于環境準備不是本文的重點,一主一從的主從複制環境可以參考此處搭建。

準備好環境,本地啟動兩個

MySQL

,主節點環境:

  • 名字:

    master

  • 端口:

    3306

  • 資料庫:兩個庫(

    test0

    test1

  • 資料表:六個表,每個庫三個(

    test0.user0

    test0.user1

    test0.user2

    test1.user0

    test1.user1

    test1.user2

從節點環境:

  • 名字:

    slave

  • 端口:

    3307

  • 資料庫:兩個庫(

    test0

    test1

  • 資料表:六個表,每個庫三個(

    test0.user0

    test0.user1

    test0.user2

    test1.user0

    test1.user1

    test1.user2

主庫配置檔案:

[mysqld]
server-id=1
binlog-do-db=test0
binlog-do-db=test1
           

從庫配置檔案:

[mysqld]
server-id=2
replicate-do-db=test0
replicate-do-db=test1
           

完整的資料庫腳本和

MySQL

配置檔案放在文末的源碼連結中。

4 建立項目

建立項目并引入如下依賴:

  • Druid

  • MyBatis Plus starter

  • MyBaits Plus Generator

  • Velocity core

  • ShardingSphere

  • Yitter

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'
           

5 配置檔案

spring:
  shardingsphere:
    datasource:
      names: master-test0,master-test1,slave-test0,slave-test1                 # 資料源節點名字
                                                                               # master-test0表示主節點的test0庫,master-test1表示主節點的test1庫
                                                                               # slave-test0表示從節點的test0庫,slave-test1表示從節點的test1庫
      master-test0:
        type: com.alibaba.druid.pool.DruidDataSource                           # 連接配接池
        url: jdbc:mysql://127.0.0.1:3306/test0                                 # 主節點的test0庫
        username: root
        password: 123456
      master-test1:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3306/test1                                 # 主節點的test1庫
        username: root
        password: 123456
      slave-test0:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3307/test0                                 # 從節點的test0庫,端口3307
        username: root
        password: 123456
      slave-test1:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3307/test1                                 # 從節點的test1庫,端口3307
        username: root
        password: 123456
    sharding:
      default-database-strategy:
        inline:
          sharding-column: age                                                 # 按照哪一列分庫
          algorithm-expression: master-test$->{age % 2}                        # 分庫規則為對年齡取模
      tables:
        user:
          actual-data-nodes: master-test$->{0..1}.user$->{0..2}                # 分表的節點,格式為 [資料源.表名]
          table-strategy:
            inline:
              sharding-column: id                                              # 按照哪一列分表
              algorithm-expression: user$->{id%3}                              # 分表規則,對id取模

      master-slave-rules:                                                      # 讀寫分離的規則
        master-test0:                                                          # 哪一個主節點
          master-datasource-name: master-test0                                 # 指定主節點名字
          slave-data-source-names: slave-test0                                 # 指定從節點名字
        master-test1:
          master-datasource-name: master-test1
          slave-data-source-names: slave-test1
    props:
      sql:
        show:
          true                                                                 # 列印SQL
           

6 準備測試代碼

使用

MyBatis 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();
    }
}
           

實體類加上

@Builder

,同時設定

id

類型為

IdType.ASSIGN_ID

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

修改

Controller

類:

@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("[email protected]").build());
    }
}
           

同時新增一個雪花

id

生成器類(具體配置方法可以參考

MyBatis Plus

官方文檔):

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();
    }
}
           

7 測試

重新整理幾次插入頁面:

http://localhost:8080/user/insert
           

從輸出可以看到插入都是在主節點中進行的:

Spring Boot demo系列(十四):ShardingSphere + MyBatisPlus 分庫分表 + 讀寫分離1 概述2 環境3 資料庫環境準備4 建立項目5 配置檔案6 準備測試代碼7 測試8 參考代碼

而查詢的時候:

http://localhost:8080/user/select
           

輸出如下:

Spring Boot demo系列(十四):ShardingSphere + MyBatisPlus 分庫分表 + 讀寫分離1 概述2 環境3 資料庫環境準備4 建立項目5 配置檔案6 準備測試代碼7 測試8 參考代碼

是在從節點查詢的。

8 參考代碼

Java

版:

  • Github
  • 碼雲
  • CODE CHINA

Kotlin

版:

  • Github
  • 碼雲
  • CODE CHINA

繼續閱讀