开发易掌握的知识:ShardingSphere+分库分表+读写分离

ShardingSphere 是 Apache 开源的 分布式数据库中间件 ,支持 分库分表、读写分离 ,能有效提升 数据库高并发处理能力 。本文通过一个 高并发订单系统 的案例,讲解 ShardingSphere 如何实现分库分表 + 读写分离

1.分库分表

✅ 方案概述

分库分表(Database & Table Sharding)是指:

  1. 分库 (Sharding Database):订单表按 user_id 进行分库,比如 user_id % 2,将数据分别存入 db_0db_1
  2. 分表 (Sharding Table):订单表在每个库中继续分表,比如 order_id % 4,将数据存入 order_0 ~ order_3
  3. 查询时 ,ShardingSphere 自动路由 SQL 到正确的数据库和表,无需应用层处理。

✅ 数据库结构

假设 2 个数据库db_0db_1),每个数据库中有 4 张订单表order_0 ~ order_3):

makefile 复制代码
db_0:
  ├── order_0
  ├── order_1
  ├── order_2
  ├── order_3
db_1:
  ├── order_0
  ├── order_1
  ├── order_2
  ├── order_3

💡 分片规则:

  • 分库:user_id % 2 = 0 → db_0, user_id % 2 = 1 → db_1
  • 分表:order_id % 4 = 0 ~ 3(4 张表)

2.读写分离

读写分离 是指:

  1. 所有写操作(INSERT, UPDATE, DELETE)走主库(Master)。
  2. 所有读操作(SELECT)走从库(Slave)。
  3. ShardingSphere 自动路由 SQL 到正确的主从库。

✅ 数据库结构

假设每个数据库 采用主从架构

scss 复制代码
db_0 (主库) → db_0_slave1, db_0_slave2
db_1 (主库) → db_1_slave1, db_1_slave2

💡 读写分离策略:

  • 写入(INSERT, UPDATE) → db_0 / db_1(主库)
  • 查询(SELECT) → db_0_slave1, db_0_slave2 / db_1_slave1, db_1_slave2

3. 高并发案例:电商订单系统

📌 场景:秒杀订单

  • 业务需求:

    1. 用户下单时,订单数据写入数据库(分库分表 + 写入主库)。
    2. 订单查询时,走从库(读写分离)。
    3. 高并发支持百万 QPS,防止数据库压力过大。

✅ 代码示例(Spring Boot + ShardingSphere)

1️⃣ 配置 sharding.yml(分库分表 + 读写分离)

yaml 复制代码
sharding:
  datasource:
    names: db_0, db_1

  # 配置主从数据源(读写分离)
  master-slave-rules:
    db_0:
      master-data-source-name: db_0
      slave-data-source-names: db_0_slave1, db_0_slave2
    db_1:
      master-data-source-name: db_1
      slave-data-source-names: db_1_slave1, db_1_slave2

  # 分库策略(user_id % 2)
  sharding-rules:
    order:
      actual-data-nodes: db_${0..1}.order_${0..3}
      table-strategy:
        inline:
          sharding-column: order_id
          algorithm-expression: order_${order_id % 4}
      database-strategy:
        inline:
          sharding-column: user_id
          algorithm-expression: db_${user_id % 2}

2️⃣ 下单(写操作,分库分表 & 主库写入)

java 复制代码
@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;

    @Transactional
    public void createOrder(Long userId, Long productId) {
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setOrderId(System.currentTimeMillis()); // 唯一 ID
        orderRepository.save(order);
    }
}

💡 ShardingSphere 自动路由 SQL

  • user_id=1001,落到 db_1
  • order_id=12345,落到 order_1
sql 复制代码
INSERT INTO db_1.order_1 (order_id, user_id, product_id) VALUES (12345, 1001, 567);

3️⃣ 查询订单(读操作,自动路由到从库)

java 复制代码
public Order getOrder(Long userId, Long orderId) {
    return orderRepository.findByUserIdAndOrderId(userId, orderId);
}

💡 ShardingSphere 自动路由 SQL

  • 查询 user_id=1001, order_id=12345,查询 db_1_slave1, db_1_slave2
sql 复制代码
SELECT * FROM db_1.order_1 WHERE user_id = 1001 AND order_id = 12345;

💡 ShardingSphere 自动使用从库,避免影响主库性能。


4. 性能优化(支持百万 QPS)

优化点 优化方式
缓存 Redis 预加载热点数据(订单查询先查 Redis)。
索引优化 order_id, user_id 建立联合索引,加速查询。
异步处理 订单入库采用 Kafka + 异步处理,避免阻塞高并发请求。
批量插入 INSERT INTO order_xxx (...) VALUES (...), (...),减少数据库连接开销。
数据库连接池 配置 HikariCP 连接池,提高数据库并发处理能力。

5.事务问题

场景 事务是否支持 解决方案
同一 MySQL 实例(多个库) 支持事务 普通事务 (START TRANSACTION)
分布式数据库(多个 MySQL 实例) 不支持事务 Seata / ShardingSphere / 事务消息
高并发分布式架构 不支持事务 基于 MQ 的最终一致性
  1. 同一 MySQL 实例内,多库事务 👉 普通事务 or XA 事务(适用于小规模应用)。
  2. 分库分表,多个 MySQL 实例 👉 ShardingSphere + 读写分离(适用于电商等大规模业务)。
  3. 分布式事务(跨多个 MySQL 实例) 👉 Seata(TCC / AT 模式)
  4. 高并发、高可用业务 👉 RocketMQ / Kafka 事务消息(最终一致性)。
相关推荐
老朋友此林5 分钟前
Redisson 实现分布式锁源码浅析
java·redis·分布式
爱分享的淘金达人18 分钟前
25年教师资格认定材料及认定详细流程‼
java·python·考研·小程序·tomcat
其实我就是个萌新20 分钟前
使用spring data MongoDB对MongoDB进行简单CURD操作示例
java·mongodb·spring
穆韵澜22 分钟前
SQL语言的云计算
开发语言·后端·golang
小小鸭程序员1 小时前
NPM版本管理终极指南:掌握依赖控制与最佳实践
java·前端·spring·npm·node.js
uhakadotcom1 小时前
提升PyODPS性能的实用技巧
后端·面试·github
字节源流1 小时前
【SpringMVC】入门版
java·后端
三少爷的鞋1 小时前
深入理解 Java 中的 Integer 缓存机制
java
MrWho不迷糊1 小时前
Spring Boot 的优雅启停:确保停机不影响交易
spring boot·后端
xjz18421 小时前
Netty底层原理深度解析:高并发网络编程的核心设计
后端