
1. 为什么需要分库分表在互联网应用快速发展的今天数据量呈现爆炸式增长。我经历过一个电商项目仅仅运营一年订单表就达到了上亿条记录单表查询性能明显下降。这时候传统的单库单表架构就遇到了瓶颈主要体现在三个方面首先是性能问题。当单表数据超过千万级别时即使有索引查询效率也会大幅下降。我实测过一个5000万数据的用户表简单分页查询耗时超过2秒完全无法满足业务需求。其次是可用性问题。所有数据集中在一个数据库实例上一旦出现故障整个系统就会瘫痪。去年我们一个核心数据库服务器硬盘损坏导致服务中断8小时损失惨重。最后是扩展性问题。单机数据库的硬件扩展存在上限无法通过简单增加服务器来提升整体性能。而分库分表可以轻松实现水平扩展。2. ShardingSphere核心组件解析2.1 Sharding-JDBC轻量级Java框架作为ShardingSphere的核心组件Sharding-JDBC给我的第一印象就是轻。它不需要额外部署直接以jar包形式集成到项目中。我在Spring Boot项目中引入它只需要添加以下依赖dependency groupIdorg.apache.shardingsphere/groupId artifactIdsharding-jdbc-spring-boot-starter/artifactId version5.1.1/version /dependency它的工作原理是在JDBC层进行拦截和路由对业务代码几乎无侵入。我特别喜欢它的这个特性因为这意味着可以平滑迁移现有项目。2.2 Sharding-Proxy数据库代理中间件对于不想改造代码的遗留系统Sharding-Proxy是个不错的选择。它作为独立服务运行对外提供与MySQL完全兼容的协议。我最近帮一个客户将他们的PHP系统迁移到分库分表环境就是通过Sharding-Proxy实现的PHP代码一行都不用改。配置示例rules: - !SHARDING tables: t_order: actualDataNodes: ds_${0..1}.t_order_${0..15} tableStrategy: standard: shardingColumn: order_id preciseAlgorithmClassName: com.demo.hash.ModuloShardingAlgorithm2.3 Sharding-Sidecar服务网格方案虽然目前还在规划中但Sharding-Sidecar代表了云原生时代的新思路。它将作为Sidecar与Service Mesh集成为各种语言的应用提供统一的数据分片能力。这个设计让我很期待因为可以解决多语言环境下的分库分表难题。3. 分库分表实战策略3.1 分片键选择经验选择合适的分片键是成功的关键。根据我的经验好的分片键应该具备以下特征高区分度如用户ID、订单ID等业务相关性经常作为查询条件稳定性不会频繁变更我曾经在一个项目中错误地选择了订单状态作为分片键结果导致大量数据集中在少数分片上完全失去了分片的意义。3.2 常见分片算法对比算法类型适用场景优点缺点我的使用建议取模数据均匀分布实现简单扩容困难适合数据量稳定的场景范围按时间或ID范围易于扩容可能热点时间序列数据首选哈希随机分布分布均匀不支持范围查询通用性最好自定义特殊业务需求灵活度高开发成本高复杂业务场景使用3.3 分布式事务处理分库分表后最大的挑战就是分布式事务。ShardingSphere提供了多种解决方案XA事务适合强一致性场景但性能较差。我在金融项目中用过TPS只能到200左右。SAGA事务最终一致性性能较好。电商订单系统推荐使用。BASE事务牺牲部分一致性换取可用性。适合对一致性要求不高的场景。我的经验是能避免分布式事务就尽量避免可以通过设计将事务限制在单个分片内。4. 生产环境踩坑实录4.1 分页查询优化分库分表后传统的LIMIT分页会出现严重问题。比如查询SELECT * FROM t_order ORDER BY create_time DESC LIMIT 10000,10需要在每个分片上都获取10010条数据然后在内存中排序。解决方案使用ShardingSphere的归并引擎改用游标分页记录最后一条记录的ID使用Elasticsearch等搜索引擎辅助查询4.2 全局ID生成方案自增ID在分库分表环境下会冲突需要全局唯一ID。我们对比了几种方案UUID最简单但无序影响索引性能Snowflake推荐方案但要注意时钟回拨问题数据库序列性能瓶颈不推荐Redis生成性能好但增加了依赖最终我们选择了改进版的Snowflake解决了时钟回拨问题单机QPS能达到10万。4.3 数据迁移方案线上系统迁移到分库分表是个大工程。我们总结了一套安全迁移流程双写阶段新老系统同时写入用canal同步老数据校验阶段开发数据比对工具确保一致性切换阶段灰度切流先切读再切写观察阶段监控各项指标随时准备回滚整个过程我们用了3周时间最终实现了平滑过渡业务无感知。5. 性能调优实战5.1 连接池配置分库分表后连接数会成倍增长。我们遇到过连接池配置不当导致的问题spring: shardingsphere: datasource: ds_0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://db1:3306/db0 username: root password: password hikari: maximum-pool-size: 20 # 每个数据源的连接数 minimum-idle: 10建议总连接数 分库数量 × 单库连接数。我们16个分片配置了320个连接16×20结果把数据库压垮了。后来调整为16×580个连接配合连接复用效果很好。5.2 SQL优化要点避免跨分片JOIN我们重构了业务逻辑将需要JOIN的数据冗余存储使用绑定表将关联表按相同规则分片如订单和订单明细IN查询优化控制IN条件数量建议不超过100个索引设计分片键必须包含在索引中5.3 监控指标我们建立了完善的监控体系重点关注分片命中率检查路由是否均匀SQL耗时分布识别慢查询连接池状态预防连接泄漏分布式事务成功率使用PrometheusGrafana搭建的监控平台可以实时掌握系统状态。6. 最佳实践总结经过多个项目的实践我总结了以下经验分库分表不是银弹单表千万以下数据不建议使用先分库再分表数据库实例比表更容易扩展做好数据迁移和回滚方案业务连续性最重要监控要跟上特别是跨分片操作团队要培训理解分片原理才能用好未来我计划尝试ShardingSphere的读写分离和数据加密功能这些特性对构建高安全性的系统很有帮助。对于刚接触分库分表的开发者建议从小规模测试开始逐步积累经验。