SpringBoot3整合ShardingSphere-Jdbc分库分表实战

 更新时间:2026年01月30日 09:33:11   作者:荒古废体  
本文主要介绍了SpringBoot3整合ShardingSphere-Jdbc分库分表实战,解决了分表和读写分离的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

网上找了很多资料,包括官网,使用springboot3shardingsphere-jdbc都无法运行,查了GPT和网上搜索,摸索了一晚上,找到了方案。

1. Maven 依赖

<dependencies>
    <!-- ShardingSphere JDBC 核心依赖 -->
     <dependency>
         <groupId>org.apache.shardingsphere</groupId>
         <artifactId>shardingsphere-jdbc</artifactId>
         <version>5.5.2</version>
     </dependency>

    <!-- Druid 数据源 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-3-starter</artifactId>
        <version>1.2.27</version>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.4.0</version>
    </dependency>
    
     <!-- springboot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.5.5</version>
    </dependency>
</dependencies>

2. application.yml 配置

新版配置分为了两个文件,一个application.yml,另一个是sharding-datasource.yml

官网上是这么说的:

1. 首先 application.yml配置

server:
  port: 9090

spring:
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver # 指定了ShardingSphereDriver 为数据库驱动
    url: jdbc:shardingsphere:classpath:sharding-datasource.yml # 指定classpath的sharding-datasource.yml文件

目录结构:

2. sharding-datasource.yml配置

mode:
  type: Standalone       # ShardingSphere 运行模式,Standalone 表示单机模式,不是集群模式
  repository:
    type: MEMORY         # 元数据存储类型,MEMORY 表示元数据存储在内存中(也可用 JDBC 存储)
dataSources:
  master:                # master名字可以自定义 数据库主库(普通表 写库)
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource  # 使用 Druid 作为真实数据源
    driverClassName: com.mysql.cj.jdbc.Driver                   # MySQL 驱动
    url: jdbc:mysql://localhost:3306/tsuki-chat?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
    username: root
    password: 123456
  slave:                 #slave名字可以自定义 数据库从库(普通表 从库)
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/tsuki-chat?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
    username: root
    password: 123456
  users_master:          # users表数据库主库(用于 users 表分库分表写入操作)
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tsuki-users?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
    username: root
    password: 123456

  users_slave:          # users表数据库从库(用于 users 表分库分表读取操作)
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/tsuki-users?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
    username: root
    password: 123456

rules:
  # 1️⃣ 全局表(除了 users 表)读写分离规则
  - !READWRITE_SPLITTING
    dataSourceGroups: # 必须用dataSourceGroups,用官网的dataSources会报错
      readwrite_ds:                     # 逻辑数据源名(可自定义)
        writeDataSourceName: master     # 写库
        readDataSourceNames:            # 读库集合
          - slave
        transactionalReadQueryStrategy: PRIMARY  # 事务读策略,PRIMARY 表示事务中读主库
        loadBalancerName: random        # 读库负载均衡策略
    loadBalancers:
      random:                           # 负载均衡算法配置
        type: RANDOM                    # 随机选择读库

  # 2️⃣ 针对users 表读写分离规则
  - !READWRITE_SPLITTING
    dataSourceGroups:
      users_group:                      # users 表逻辑数据源名(可自定义)
        writeDataSourceName: users_master  # 写库
        readDataSourceNames:
          - users_slave # 读库
        transactionalReadQueryStrategy: PRIMARY  # 事务读策略,PRIMARY 表示事务中读主库
        loadBalancerName: random        # 读库负载均衡策略
    loadBalancers:
      random:
        type: RANDOM                    # 随机负载均衡

  # 3️⃣ users 表分表规则
  - !SHARDING
    tables:
      users:
        actualDataNodes: users_group.users_${0..1}   # 物理表名列表,users_0 和 users_1
        tableStrategy:
          standard:
            shardingColumn: id                 # 分表字段
            shardingAlgorithmName: user_algo   # 使用分片算法 user_algo
    shardingAlgorithms:
      user_algo:
        type: INLINE
        props:
          algorithm-expression: users_${id % 2}  # 简单取模算法,将 id % 2 决定插入到 users_0 或 users_1

  # 4️⃣ 其他非分片表(比如 Test、Message 等)走默认读写分离数据源
  - !SINGLE
    tables:
      - "*.*"                             # 匹配所有其他表
    defaultDataSource: readwrite_ds       # 使用逻辑数据源 readwrite_ds(即 tsuki-chat 的读写分离)

props:
  sql-show: true                         # 打印 SQL,便于调试
  check-table: false                      # 不检查表是否存在,防止启动报错
  default-data-source-name: readwrite_ds  # 默认逻辑数据源

3. 配置要点

  • 读写分离

    • 默认库 (tsuki-chat) → 主从 master/slave
    • users 专库 (tsuki-users) → 主从 users_master/users_slave
  • 分表users 表按照 id % 2 分为 users_0users_1

  • 普通表:通过 !SINGLE 指定默认走 readwrite_ds,避免 TableNotFoundException

  • 元数据模式repository: MEMORY → 元数据存放在内存中,开发环境方便测试。

4. 数据库

数据库首先必须配置主从同步,最好从库禁用插入(这里教程很多,网上自己搭建)
首先有2个数据源,一共4个库
tsuki-chat是我的普通表库,用于存放不用分库分表的库
tsuki-users是我的分库分表库,用于users表分表


users分库分表(我有两张表)

4. 常见问题

  1. 报错 TableNotFoundException → 没有配置 !SINGLE,需要为非分片表指定默认数据源。
  2. 事务中读操作跑到从库 → 配置 transactionalReadQueryStrategy: PRIMARY,保证事务一致性。
  3. 测试数据回滚导致表为空 → 注意是否加了 @Transactional 测试注解。

5. 测试

1. 测试普通表插入

    @Test
    public void test3() {
        DbTest dbTest = new DbTest(1);
        testMapper.insert(dbTest);
    }

输出

2025-09-03T14:34:04.361+08:00  INFO 48308 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO db_test  ( id )  VALUES (  ?  )
2025-09-03T14:34:04.362+08:00  INFO 48308 --- [           main] ShardingSphere-SQL                       : Actual SQL: master ::: INSERT INTO db_test  ( id )  VALUES (  ?  ) ::: [114514]
2025-09-03T14:34:04.436+08:00  INFO 48308 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closing ...
2025-09-03T14:34:04.440+08:00  INFO 48308 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed

我们可以看到输出了Actual SQL: master ::: INSERT INTO db_test ( id ) VALUES ( ? ) ::: [114514],说明写入走了master
同时从库也有了数据

2. 测试普通表查询

    @Test
    public void test4() {
        DbTest dbTest = testMapper.selectById(114514);
        log.info(dbTest.toString());
    }

输出

2025-09-03T14:39:28.865+08:00  INFO 37376 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT id FROM db_test WHERE id=?
2025-09-03T14:39:28.865+08:00  INFO 37376 --- [           main] ShardingSphere-SQL                       : Actual SQL: slave ::: SELECT id FROM db_test WHERE id=? ::: [114514]
2025-09-03T14:39:28.914+08:00  INFO 37376 --- [           main] c.t.c.server.TestChatServerApplication   : DbTest(id=114514)

我们可以看到输出了Actual SQL: slave ::: SELECT id FROM db_test WHERE id=? ::: [114514],说明读取入走了slave
同时从库也有了数据。
普通表读写测试分离成功

3. 测试users表插入

    @Test
    public void test() {
        List<User> users = generateUsers(10); // 生成10条users数据
        List<BatchResult> insert = userMapper.insert(users);
        log.info("插入成功");
    }

输出

2025-09-03T15:00:10.253+08:00  INFO 47088 --- [           main] ShardingSphere-SQL                       : Actual SQL: users_master ::: INSERT INTO users_1  ( id, username, nickname, signature, email, password, avatar, mobile, login_date, logout_date, login_ip, join_type, sex, status, creator, create_time, updater, update_time, deleted )  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ::: [1756882805969, userUbKYU, nickVpxsL, 签名AWTLp, userUbKYU@example.com, rjctPdFh, https://example.com/avatar/vYJQ.png, 15172505127, 2025-09-02T15:00:05.960025800, 2025-08-31T15:00:05.960025800, 192.168.215.80, 1, 1, 1, system, 2025-08-21T15:00:05.960025800, system, 2025-09-03T15:00:05.960025800, false]
2025-09-03T15:00:10.356+08:00  INFO 47088 --- [           main] c.t.c.server.TestChatServerApplication   : 插入成功

我们可以看到输出了Actual SQL: users_master ::: INSERT INTO users_1 ,说明写入走了users_master
同时从库也有了数据

4. 测试users表查询

    @Test
    public void test2() {
        Page<User> userPage = new Page<User>(1, 8);
        Page<User> selectedPage = userMapper.selectPage(userPage, null);
        selectedPage.getRecords().forEach(user -> log.info(String.valueOf(user.getId())));
    }

输出

2025-09-03T15:07:54.450+08:00  INFO 25284 --- [           main] ShardingSphere-SQL                       : Actual SQL: users_slave ::: SELECT  id,username,nickname,signature,email,password,avatar,mobile,login_date,logout_date,login_ip,join_type,sex,status,creator,create_time,updater,update_time,deleted  FROM users_1 LIMIT ? ::: [8]
2025-09-03T15:07:54.483+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805958
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805960
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805962
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805964
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805966
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805961
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805963
2025-09-03T15:07:54.484+08:00  INFO 25284 --- [           main] c.t.c.server.TestChatServerApplication   : 1756882805965

我们可以看到输出了Actual SQL: users_slave ::: SELECT ,说明读取走了users_slave

✅ 这样配置后:

  • users 表支持 分库 + 分表 + 读写分离
  • testorders 等普通表支持 全局读写分离
  • SQL 路由清晰可控,适合生产环境逐步扩展。

到此这篇关于SpringBoot3整合ShardingSphere-Jdbc分库分表实战的文章就介绍到这了,更多相关SpringBoot ShardingSphere-Jdbc分库分表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Clojure 与Java对比少数据结构多函数胜过多个单独类的优点

    Clojure 与Java对比少数据结构多函数胜过多个单独类的优点

    这篇文章主要介绍了Clojure 与Java对比少数据结构多函数胜过多个单独类的优点,在Clojure中,我们一次又一次地使用相同的数据结构,并在其上运行许多函,更多相关介绍需要的朋友可以参考一下下面文章内容
    2022-06-06
  • JAVA实现RSA签名、验签全过程

    JAVA实现RSA签名、验签全过程

    文章介绍了如何使用Java实现RSA签名和验签,以确保数据传输的安全性,包括生成公私钥对、使用私钥签名和公钥验签的流程,提供了三个工具类:Rsa.java、Base64.java和BaseHelper.java,示例展示了如何将业务参数排序并生成签名,以及如何验证接收到的参数签名
    2025-10-10
  • Java中Shiro安全框架的权限管理

    Java中Shiro安全框架的权限管理

    这篇文章主要介绍了Java中Shiro安全框架的权限管理,Apache Shiro是Java的一个安全框架,Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境,需要的朋友可以参考下
    2023-08-08
  • Maven jar包下载失败问题的处理方法

    Maven jar包下载失败问题的处理方法

    很多同学在Maven里下载一些依赖的时候,即下载jar包的时候总是会出现一些问题,本文将就这个问题给大家详细的讲解一下,需要的朋友可以参考下
    2023-06-06
  • java局域网聊天小程序

    java局域网聊天小程序

    这篇文章主要为大家详细介绍了java局域网聊天小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 详解Spring Aop实例之xml配置

    详解Spring Aop实例之xml配置

    本篇文章主要介绍了详解Spring Aop实例之xml配置,使用xml可以对aop进行集中配置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • SpringBoot+websocket实现消息对话功能

    SpringBoot+websocket实现消息对话功能

    WebSocket是一种在Web应用程序中实现实时双向通信的技术,它可以用于在线游戏、在线聊天、推送通知、实时监控等,并且比传统的轮询技术更加高效和可靠,本文就给大家介绍基于SpringBoot+websocket实现消息对话功能,感兴趣的小伙伴可以自己动手试一试
    2023-09-09
  • Java SiteMesh新手学习教程代码案例

    Java SiteMesh新手学习教程代码案例

    这篇文章主要介绍了Java SiteMesh新手学习教程代码案例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java中Map的用法详解

    Java中Map的用法详解

    将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口
    2016-05-05
  • 对Java接口进行幂等性控制的三种方法

    对Java接口进行幂等性控制的三种方法

    在做分布式系统、支付系统、电商秒杀等实际项目中,我们经常会遇到接口被重复调用的问题,像用户支付时多次点击“支付”按钮,消息队列消费失败后自动重试等,这些行为如果没有控制好幂等性,会产生重复数据,所以本文给大家介绍了对Java接口进行幂等性控制的三种方法
    2025-06-06

最新评论