Apache ShardingSphere 入门实战:从零搭建分布式数据库系统

1次阅读
没有评论

共计 2431 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点:为什么需要分布式数据库

当业务数据量增长到百万级甚至更高时,单机 MySQL 会遇到明显的性能瓶颈:

Apache ShardingSphere 入门实战:从零搭建分布式数据库系统

  • 数据量超过 500 万后,即使有索引查询速度也会明显下降
  • 高并发写入场景下,磁盘 IO 和 CPU 容易成为瓶颈
  • 单表数据过大时,ALTER TABLE 等 DDL 操作可能锁表数小时
  • 备份恢复时间长,故障恢复风险窗口大

技术选型:为什么选择 ShardingSphere

常见的分布式数据库方案主要有三种:

  1. 分布式数据库原生方案(如 TiDB、OceanBase)
  2. 优点:开箱即用,兼容 MySQL 协议
  3. 缺点:迁移成本高,生态工具需要适配

  4. 中间件 + 单机数据库方案(如 MyCAT)

  5. 优点:不改动现有数据库
  6. 缺点:功能相对简单,社区活跃度低

  7. ShardingSphere 方案

  8. 完整生态:支持分片、读写分离、加密、影子库等
  9. 低侵入性:可透明化接入现有系统
  10. 灵活扩展:支持自定义分片算法

核心实现

分片算法原理

ShardingSphere 支持两种基础分片策略:

  • 精确分片:=, IN 等精确匹配条件

    // 按用户 ID 取模分片
    public class UserIdPreciseSharding implements PreciseShardingAlgorithm<Long> {
        @Override
        public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {return "ds" + (shardingValue.getValue() % 2);
        }
    }

  • 范围分片:BETWEEN, >, < 等范围条件

    // 按订单日期范围分片
    public class OrderDateRangeSharding implements RangeShardingAlgorithm<Date> {
        @Override
        public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {// 返回所有可能命中的分片}
    }

Spring Boot 集成示例

  1. 添加 Maven 依赖

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
        <version>5.3.0</version>
    </dependency>

  2. 配置 YAML 文件

    spring:
      shardingsphere:
        datasource:
          names: ds0,ds1
          ds0:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.jdbc.Driver
            jdbc-url: jdbc:mysql://localhost:3306/db0
            username: root
            password: 123456
          ds1:
            # 配置同 ds0...
    
        rules:
          sharding:
            tables:
              t_order:
                actual-data-nodes: ds$->{0..1}.t_order_$->{0..15}
                database-strategy:
                  standard:
                    sharding-column: user_id
                    precise-algorithm-class-name: com.example.UserIdPreciseSharding
                table-strategy:
                  standard:
                    sharding-column: order_id
                    precise-algorithm-class-name: com.example.OrderIdPreciseSharding

性能考量

分片键选择黄金法则

  • 选择高基数(区分度高)的列:如用户 ID 比性别更适合
  • 避免选择频繁更新的列:分片键修改会导致数据迁移
  • 业务常用查询条件:WHERE user_id=123 应当能路由到具体分片

分布式事务方案

  1. XA 事务(强一致)

    spring.shardingsphere.rules.sharding.default-database-strategy.standard.xa-transaction-manager-type: Atomikos

  2. Seata 柔性事务(最终一致)

    spring.shardingsphere.rules.sharding.default-database-strategy.standard.transaction-type: BASE

连接池优化建议

  • 每个物理分片配置独立连接池
  • HikariCP 推荐配置:
    ds0:
      hikari:
        maximum-pool-size: 20
        minimum-idle: 5
        connection-timeout: 30000

避坑指南

分片键三大误区

  1. 使用自增主键作为分片键:会导致新数据集中写入最后一个分片
  2. 使用 UUID 作为分片键:无法保证均匀分布且范围查询效率低
  3. 使用枚举值作为分片键:如性别只有 2 个值,无法有效分片

跨分片查询优化

  • 避免无分片条件的全表扫描
  • 使用绑定表减少 JOIN 查询复杂度:
    spring.shardingsphere.rules.sharding.binding-tables: t_order,t_order_item
  • 合理使用广播表(如省份字典表)

数据迁移注意事项

  1. 双写迁移步骤:

  2. 配置新旧库双写

  3. 全量数据迁移
  4. 增量数据追平
  5. 流量切换验证
  6. 下线旧库

  7. 使用 ShardingSphere-Scaling 工具

    bin/start.sh --config=conf/config.yaml

思考题

如何设计一个适合订单系统的分片策略?考虑以下因素:
– 订单查询主要按用户维度
– 需要支持按时间范围查询
– 商户需要查看自己所有订单

(提示:可以尝试组合分片策略)

正文完
 0
评论(没有评论)