当前位置: 首页 > news >正文

Spring Boot + ShardingSphere 实现分库分表 + 读写分离实战

🚀 Spring Boot + ShardingSphere 实现分库分表 + 读写分离(涵盖99%真实场景)

🏷️ 标签:ShardingSphere、分库分表、读写分离、MySQL 主从、Spring Boot 实战

分库分表 vs 读写分离 vs 主从配置与数据库高可用架构区别


📚 目录导航

  • 🔍 一、场景说明
  • 🧱 二、架构图
  • ⚙️ 三、核心配置
  • 🗃️ 四、数据库建表SQL
  • 👨‍💻 五、关键代码
  • 🧪 六、测试验证
  • 🧠 七、总结与建议

🔍 一、场景说明

🚨 实际项目中,数据库面临两类瓶颈:

  • 📌 数据量太大 → 单库单表撑不住 → 使用 分库分表 拆解压力
  • 📌 读操作压力太大 → 单库处理不过来 → 使用 读写分离 转移压力

⚡ 本项目整合了这两类方案,构建如下特性系统:

  • 两个逻辑库 ds0ds1
  • ds0 搭建一主两从(主库:ds0,从库:ds0_slave1,ds0_slave2)
  • 表按照用户 ID 分片(user_id % 2)
  • 主写从读,轻松实现读写分离

🧱 二、架构图

在这里插入图片描述

📝 说明:

  • 用户通过 Controller 发起请求
  • ShardingSphere JDBC 根据操作类型选择库、表
  • 如果是写入操作,走 ds0ds1 的主库
  • 如果是读取操作,优先走 ds0_slave1ds0_slave2 从库,减轻主库压力

⚙️ 三、核心配置(application.yml)

🧩 我们通过配置 ShardingSphere 的两类规则:shardingreadwrite-splitting 实现业务目标。

spring:shardingsphere:datasource:names: ds0, ds1, ds0_slave1, ds0_slave2ds0:type: com.zaxxer.hikari.HikariDataSourcejdbc-url: jdbc:mysql://mysql-master:3307/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: rootds0_slave1:type: com.zaxxer.hikari.HikariDataSourcejdbc-url: jdbc:mysql://mysql-slave1:3308/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: rootds0_slave2:type: com.zaxxer.hikari.HikariDataSourcejdbc-url: jdbc:mysql://mysql-slave2:3309/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: rootds1:type: com.zaxxer.hikari.HikariDataSourcejdbc-url: jdbc:mysql://mysql-master:3306/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: root123456rules:sharding:tables:t_user:# 注意:此处使用物理库名(ds0、ds1)来定义 actual-data-nodesactual-data-nodes: ds$->{0..1}.t_user_$->{0..1}database-strategy:standard:sharding-column: user_idsharding-algorithm-name: database_inlinetable-strategy:standard:sharding-column: user_idsharding-algorithm-name: table_inlinekey-generate-strategy:column: idkey-generator-name: snowflakesharding-algorithms:database_inline:type: INLINEprops:algorithm-expression: ds${user_id % 2}table_inline:type: INLINEprops:algorithm-expression: t_user_${user_id % 2}key-generators:snowflake:type: SNOWFLAKEreadwrite-splitting:data-sources:rw_ds0:static-strategy:write-data-source-name: ds0read-data-source-names: [ds0_slave1,ds0_slave2]load-balancer-name: round_robinrw_ds1:static-strategy:write-data-source-name: ds1read-data-source-names: [ds1]load-balancer-name: round_robinload-balancers:round_robin:type: ROUND_ROBINprops:sql-show: truelogging:level:org.apache.shardingsphere: DEBUG

1. 数据源配置 (datasource)

定义了 4 个 MySQL 数据源(2 个主库 ds0/ds1 和 2 个从库 ds0_slave1/ds0_slave2)。

配置项说明
spring.shardingsphere.datasource.names数据源名称列表:ds0, ds1, ds0_slave1, ds0_slave2
ds0.jdbc-url主库 ds0 的 JDBC 连接 URL(端口 3307)
ds0.username主库 ds0 用户名(root
ds0.password主库 ds0 密码(root
ds0_slave1.jdbc-url从库 ds0_slave1 的 JDBC URL(端口 3308)
ds0_slave2.jdbc-url从库 ds0_slave2 的 JDBC URL(端口 3309)
ds1.jdbc-url主库 ds1 的 JDBC URL(端口 3306,与 ds0 不同实例)

2. 分片规则 (sharding)

配置表 t_user 的分片策略和分布式 ID 生成。

分片表配置
配置项作用示例值说明
tables.t_user.actual-data-nodes定义物理节点ds$->{0..1}.t_user_$->{0..1}表达式生成所有物理表,如 ds0.t_user_0ds1.t_user_1
tables.t_user.database-strategy.standard.sharding-column分库列user_id根据 user_id 计算数据存储的库。
tables.t_user.database-strategy.standard.sharding-algorithm-name分库算法名称database_inline引用 sharding-algorithms 中定义的算法。
tables.t_user.table-strategy.standard.sharding-column分表列user_id根据 user_id 计算数据存储的表。
tables.t_user.table-strategy.standard.sharding-algorithm-name分表算法名称table_inline引用 sharding-algorithms 中定义的算法。
tables.t_user.key-generate-strategy.column主键列id指定自动生成主键的列。
tables.t_user.key-generate-strategy.key-generator-name主键生成器名称snowflake使用 Snowflake 算法生成分布式 ID。
分片算法
配置项作用示例值说明
sharding-algorithms.database_inline.type算法类型INLINE使用行表达式(Inline)分片算法。
sharding-algorithms.database_inline.props.algorithm-expression分库表达式ds${user_id % 2}根据 user_id % 2 计算库索引(0 或 1)。
sharding-algorithms.table_inline.type算法类型INLINE使用行表达式分片算法。
sharding-algorithms.table_inline.props.algorithm-expression分表表达式t_user_${user_id % 2}根据 user_id % 2 计算表索引(0 或 1)。
分布式 ID
配置项作用示例值说明
key-generators.snowflake.type主键生成器类型SNOWFLAKE使用 Snowflake 算法生成分布式唯一 ID。

3. 读写分离规则 (readwrite-splitting)

配置读写分离数据源和负载均衡策略。

数据源 rw_ds0
配置项说明
write-data-source-name写库数据源:ds0(主库)
read-data-source-names读库数据源列表:[ds0_slave1, ds0_slave2](两个从库)
load-balancer-name负载均衡算法:round_robin(轮询)
数据源 rw_ds1
配置项说明
write-data-source-name写库数据源:ds1(主库)
read-data-source-names读库数据源列表:([ds1]),表示仅使用写库读
load-balancer-name负载均衡算法:round_robin(未实际生效)
负载均衡器
配置项说明
round_robin.type算法类型:ROUND_ROBIN(轮询调度)

4. 属性配置 (props)

配置项说明
sql-show: true打印 SQL 日志(便于调试)

配置逻辑总结

spring:shardingsphere:datasource:names: ds0, ds1, ds0_slave1, ds0_slave2
  • 定义三个数据源

    • ds0: 主库
    • ds0_slave: 从库(ds0 复制)
    • ds1: 第二个分片主库
    rules:sharding:tables:t_user:actual-data-nodes: rw_ds$->{0..1}.t_user_$->{0..1}
  • t_user 分片规则:共有 2 库 x 2 表 结构
            table-strategy:standard:sharding-column: user_idsharding-algorithm-name: user_inline
  • 按照 user_id 做分片(水平拆表)
        sharding-algorithms:user_inline:type: INLINEprops:algorithm-expression: t_user_${user_id % 2}
  • 表名后缀 = user_id % 2,如 t_user_0t_user_1

      readwrite-splitting:data-sources:rw_ds0:static-strategy:write-data-source-name: ds0read-data-source-names: [ds0_slave1,ds0_slave1]
  • 配置 rw_ds0 为读写分离库
  • ds0 负责写入,ds0_slave1,ds0_slave2 负责读取
          rw_ds1:static-strategy:write-data-source-name: ds1read-data-source-names: [ds1]
  • ds1 暂无从库,只支持主库写读

潜在问题

  1. rw_ds1 无读库

    • 配置中 rw_ds1.read-data-source-namesds1,可能导致读请求全部发往主库 ds1,增加压力。
  2. 分片与读写分离结合

    • 实际数据节点 rw_ds0.t_user_0rw_ds1.t_user_1 的分片逻辑需确保数据均匀分布。

🗃️ 四、数据库建表SQL

db0db1 上执行以下语句,创建两个分表:

CREATE TABLE t_user_0 (id BIGINT PRIMARY KEY,username VARCHAR(100),user_id INT
);CREATE TABLE t_user_1 LIKE t_user_0;

📌 ds0_slave1, ds0_slave2 是主库 ds0 的复制库,MySQL 自动同步,无需手动建表。


👨‍💻 五、关键代码

✅ 项目概览

sharding-demo/
├── src/
│   ├── main/
│   │   ├── java/com/example/shardingdemo/
│   │   │   ├── controller/
│   │   │   ├── entity/
│   │   │   ├── mapper/
│   │   │   ├── ShardingDemoApplication.java
│   └── resources/
│       ├── application.yml
├── pom.xml

✅ User 实体类

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {private Long id;private String username;private Integer userId; // 分片键
}

✅ Mapper 接口

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shardingdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {}

✅ Controller 控制器

import com.example.shardingdemo.entity.User;
import com.example.shardingdemo.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {private final UserMapper userMapper;@PostMapping("/add")public String addUser(@RequestParam String name, @RequestParam Integer userId) {User user = new User(System.currentTimeMillis(), name, userId);userMapper.insert(user);return "User added.";}@GetMapping("/list")public List<User> selectList() {return userMapper.selectList(null);}@GetMapping("/selectById")public User selectById(Long id){return userMapper.selectById(id);}}

🧪 六、测试验证

✅ 添加用户

http://localhost:8080/user/add?name=Alice&userId=11

控制台输出:

Actual SQL: rw_ds1 ::: INSERT INTO t_user_1 ...

✅ 说明:

  • userId = 11,落到 rw_ds1(ds1)
  • 且表名为 t_user_1,符合 % 2 = 1 的路由逻辑

🧠 七、总结与建议

特性说明
💡 分库分表扩展写能力,解决单表瓶颈
💡 读写分离减轻主库压力,提高系统吞吐
✅ 可扩展性新增库或表只需扩展路由规则,无需修改业务代码
✅ 高性能多线程批量插入、查询等场景提升明显
🔒 安全性通过主从架构,规避读阻塞或死锁导致系统不可用

📢 建议配合 Docker + MySQL 主从配置部署验证,效果最佳。


❤️ 如果你觉得这篇文章有帮助:

  • 点赞 👍
  • 收藏 ⭐
  • 留言 💬
http://www.lryc.cn/news/609763.html

相关文章:

  • AWS VPC Transit Gateway 可观测最佳实践
  • 【物联网】基于树莓派的物联网开发【23】——树莓派安装SQLite嵌入式数据库
  • 16_OpenCV_漫水填充(floodFill)
  • Nginx vs Spring Cloud Gateway:限流功能深度对比与实践指南
  • Spring Cloud Gateway 实现登录校验:构建统一认证入口
  • 图片的放大缩小选择全屏
  • XSS的原型链污染1--原型链解释
  • 笔记本电脑联想T14重启后无法识别外置红米屏幕
  • Django + Vue 项目部署(1panel + openresty)
  • AI“炼金术”:破解绿色水泥的配方密码
  • 三防平板电脑是什么?这款三防平板支持红外测温!
  • 电脑上不了网怎么办?【图文详解】wifi有网络但是电脑连不上网?网络设置
  • 电脑一键重装系统win7/win10/win11无需U盘(无任何捆绑软件图文教程)
  • Ribbon 核心原理与架构详解:服务负载均衡的隐形支柱
  • 工作流绑定卡片优化用户体验-练习我要找工作智能体
  • 【CVPR2025】计算机视觉|AnomalyNCD:让工业异常分类“脱胎换骨”!
  • transformer与神经网络
  • ubuntu24.01安装odoo18
  • 纯前端使用ExcelJS插件导出Excel
  • 计算机视觉(2)车规摄像头标准
  • 5天挑战网络编程 -DAY1(linux版)
  • python:讲懂决策树,为理解随机森林算法做准备,以示例带学习,通俗易懂,容易理解和掌握
  • 句子表征-文本匹配--representation-based/interactive-based
  • 学习日志27 python
  • 基于开源AI智能名片链动2+1模式与S2B2C商城小程序的直播营销销量转化机制研究
  • 短剧小程序系统开发:引领影视消费新潮流
  • 【世纪龙科技】汽车自动变速器拆装虚拟实训软件
  • 音视频文案字幕一键提取,免费使用,效率软件!
  • AR远程协作网页设计:虚实融合场景下的故障标注与操作指引界面
  • AR技术赋能轨道交通培训:虚实结合提升学习效率