开发易掌握的知识: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 事务消息(最终一致性)。
相关推荐
爱敲代码的三毛7 分钟前
RabbitMQ可靠性进制
java·分布式·rabbitmq
往日情怀酿做酒 V17639296388 分钟前
Django项目之订单管理part3
后端·python·django
uhakadotcom1 小时前
MaxCompute Python UDF开发指南:从入门到精通
后端·面试·github
云上艺旅1 小时前
K8S学习之基础三十一:k8s中RBAC 的核心概念
java·学习·云原生·kubernetes
追寻光1 小时前
Java 绘制图形验证码
java·前端
前端snow1 小时前
爬取数据利用node也行,你知道吗?
前端·javascript·后端
2301_792185881 小时前
maven的安装配置
java·maven
霸王龙的小胳膊1 小时前
SpringMVC-文件上传
java·mvc
哥谭居民00011 小时前
mybatis注册一个自定义拦截器,拦截器用于自动填充字段
java·开发语言·jvm·mybatis
陈随易1 小时前
告别Node.js:2025年,我为何全面拥抱Bun
前端·后端·程序员