几乎所有项目都会经历这样一个过程,业务初期数据量小,单表百万级数据,普通索引、基础SQL完全能稳稳支撑业务;但随着用户体量、订单流水、日志数据持续暴涨,单表数据突破千万、直奔上亿时,所有隐藏问题会集中爆发:接口响应变慢、高峰期数据库卡顿、查询超时、写入延迟升高。
我们也完整走完了这一整套曲折的优化之路,从最基础的调参改SQL,到早期中间件选型踩坑,再到最终落地成熟稳定的分布式数据库架构,每一步都是线上真实故障打磨出来的经验。
最开始,我们坚信优化能解决一切问题:反复调整MySQL全局配置、逐行优化慢SQL、批量梳理新增索引、清理冗余字段。但很快发现,所有优化都只是「续命手段」,无法根治上亿级数据的底层瓶颈。一个系统四百多张表,随便划拉几张基本上都是上千万上亿的数据量,单纯的优化已经解决不了问题。
然后我们开始研究分库分表中间件,早期因ShardingSphere生态不成熟,首选行业主流的Mycat搭建架构;但随着业务迭代、技术栈升级,Mycat的兼容性、性能瓶颈、SQL 支持受限、更重要的一点运维配置极其复杂、稳定性短板彻底暴露,最终我们完成全量迁移,落地ShardingSphere JDBC + Proxy 双架构,同时搭配主从读写分离,形成适配高并发、亿级数据的最终稳定方案。
一路走来,很多核心疑问困扰了我们很久:
✅ JDBC 和 Proxy 两种架构到底该怎么选型?各自适配什么业务场景?
✅ 两种模式配置差异、Spring版本兼容区别在哪里?
✅ 什么场景只分表、什么场景必须分库?对SQL查询有哪些影响?
✅ 分库分表如何和主从读写分离完美联动,实现性能最大化?
今天结合我们完整踩坑演进史 + 线上落地 + 生产选型标准,给大家分享一下。
一、核心选型:ShardingSphere JDBC / Proxy 到底怎么选?
1、ShardingSphere-JDBC 适配场景
核心定位:无中间件、零损耗、高性能、Java核心业务专属
- 核心交易、订单、支付、流水等高并发 OLTP 业务
- 全站技术栈为 Java/SpringBoot,无多语言异构服务
- 追求极致响应速度,无法接受额外网络转发损耗
- 团队运维人手有限,不想新增中间件维护成本
本质:Jar包嵌入业务进程,直连分片数据库,无中心化节点、无网络转发,性能最优。
这也是我们部分选择用这种方式的原因,由于我们的数据支持第三方回流,一直处于高并发的状态。
2、ShardingSphere-Proxy 适配场景
核心定位:统一入口、集中治理、多语言兼容、低侵入改造
- 后台统计、报表、数据导出、大数据量慢查询等 OLAP 业务
- 存在 Go/Python/PHP 等非Java服务访问分片数据
- 老旧系统改造,不想改动业务代码,仅更换数据库连接地址
- 微服务实例数量多,JDBC模式易打爆MySQL连接数
- 需要DBA直接通过Navicat操作分片库、统一管理分片规则
本质:独立代理服务,统一接管所有数据库请求,连接集中复用,牺牲微量性能,换取极强的运维可控性。
3、我们最终落地策略
- 核心交易服务 = JDBC:保障高并发、低延迟、高可用
- 非核心报表/第三方服务 = Proxy:统一治理、降低运维成本、规避连接爆炸问题
二、深度对比:JDBC vs Proxy 配置差异、Spring版本兼容区别
1、核心配置与架构差异
| 对比项 | ShardingSphere-JDBC | ShardingSphere-Proxy |
|---|---|---|
| 部署方式 | Jar内嵌,随SpringBoot项目启动 | 独立进程、独立端口、集群部署 |
| 配置位置 | 各业务服务yml配置,分散管理 | Proxy统一配置 + Nacos动态配置 |
| 规则更新 | 修改配置需重启业务服务 | 动态刷新,业务服务无需重启 |
| 数据库连接 | 多实例会放大连接数,易打满MySQL上限 | 连接集中复用,彻底解决连接爆炸 |
| 性能损耗 | 几乎0损耗 | 多一层网络转发,轻微性能损耗 |
| 代码侵入 | 需引入依赖、配置分片规则 | 零代码侵入,仅改连接地址 |
2、Spring/JDK 版本兼容核心区别(避坑重点)
- Mycat:完全不兼容 SpringBoot3、JDK17+,新技术栈项目直接阵亡,是淘汰核心原因
- ShardingSphere-JDBC 5.3+:全版本兼容,支持 SpringBoot2.x/3.x、JDK8~JDK21,适配虚拟线程新项目
- ShardingSphere-Proxy:无Spring、JDK依赖,完全独立运行,新旧业务、不同技术栈可统一接入,改造兼容性拉满
三、生产核心规范:分表、分库适用场景 + SQL查询影响
很多项目架构臃肿、SQL难写、分布式事务泛滥,核心原因是:不分场景乱分库、乱分表。我们经过多次踩坑,总结出严格的生产落地标准。当然更多的还是要根据具体的业务来分析。
1、只分表、不分库(90%亿级数据场景首选)
适用条件:
- 单表数据破千万/上亿,单库 CPU、内存、IO 压力正常,无硬件瓶颈
- 业务QPS高、数据量大,但单机数据库可承载
- 无大量跨库联表、跨库事务需求
典型业务:订单表、支付流水表、操作日志表、用户行为记录表
SQL查询影响:
- 同库分片,联表查询、分页排序兼容性极好
- 无跨库网络开销,查询性能稳定高效
- 几乎规避分布式事务,业务复杂度极低
2、必须分库(仅极端瓶颈场景)
适用条件(全部满足才执行):
- 单库硬件常年打满:CPU持续高负载、IO打满、连接数爆满
- 数据量、QPS双高,单库物理性能达到上限
- 单表分片优化后,依旧无法缓解数据库压力
SQL查询影响(高危避坑):
- 严格禁止随意跨库JOIN,极易引发性能雪崩
- 跨库分页、排序、聚合查询成本大幅提升
- 必须依赖分布式事务,架构复杂度、运维成本翻倍
生产铁律
能分表不分库、能不分就不拆分。分表是优化手段,分库是最终兜底方案。
四、架构联动:ShardingSphere + 主从读写分离方案
分片解决单表数据量大的存储瓶颈,读写分离解决查询QPS过高的并发瓶颈,二者必须联动使用,才能实现架构最优解。
1、整体架构链路
- 主库:全权承载新增、更新、删除、事务写操作,保证数据一致性
- 从库集群:承载所有列表查询、分页、统计、导出、慢查询,分流主库压力
- ShardingSphere统一接管:自动完成分片路由 + 读写分离路由,业务无感知
2、双架构分工策略
- JDBC核心服务:读写分离+分片双重路由,保障核心交易读写均衡、低延迟
- Proxy报表服务:所有OLAP慢查询、大数据量统计全部引流至从库,彻底隔离读写压力,不影响核心交易
3、核心避坑要点
- 读写分离无法解决单表数据量大的问题,只能扛并发,必须配合分片/归档使用
- 分片无法解决查询并发压力,必须靠读写分离分流QPS
- 最终治理链路:基础优化 → 冷热数据归档 → 单表分片 → 读写分离 → 极端场景分库
五、以下部分配置Demo:JDBC + Proxy 完整配置
1、SpringBoot3 + ShardingSphere-JDBC 完整配置(分表+读写分离)
核心依赖 pom.xml
sharding-config.yaml文件配置部分截图,当然也可以直接在application.yaml配置
application.yml 完整可上线配置
spring: shardingsphere: # 多数据源配置:主库+从库 datasource: names: master,slave1 master: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/db_master username: root password: xxx slave1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/db_slave username: root password: xxx # 读写分离规则 rules: readwrite-splitting: >2、ShardingSphere-Proxy 完整可上线配置Proxy 无需改动业务代码,仅需配置服务端规则,业务侧修改连接地址即可,适配所有技术栈。
server.yaml(全局配置)
mode: type: Cluster repository: type: Nacos props: nacos-server-addr: 127.0.0.1:8848 nacos-namespace: public nacos-group: DEFAULT_GROUP # 认证配置 authentication: users: root: password: xxx sharding: password: xxx # 全局属性 props: sql-show: true sql-simple: true max-connections-size-per-query: 10
config-sharding.yaml(分片+读写分离核心规则)
databaseName: sharding_db # 数据源配置 dataSources: master: url: jdbc:mysql://127.0.0.1:3306/db_master?useSSL=false&serverTimezone=Asia/Shanghai username: root password: xxx connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 600000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 20 slave1: url: jdbc:mysql://127.0.0.1:3306/db_slave?useSSL=false&serverTimezone=Asia/Shanghai username: root password: xxx connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 600000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 20 # 读写分离规则 rules: - !READWRITE_SPLITTING dataSources: ds: writeDataSourceName: master readDataSourceNames: - slave1 loadBalancerName: round_robin # 分表规则 - !SHARDING tables: order_info: actualDataNodes: ds.order_info_${0..3} tableStrategy: standard: shardingColumn: user_id shardingAlgorithmName: user_id_mod_4 shardingAlgorithms: user_id_mod_4: type: MOD props: sharding-count: 4
业务侧接入方式
业务项目直接连接 Proxy 地址,无需任何分片、读写分离配置,和正常连接MYSQL数据库一样:
spring: datasource: url: jdbc:mysql://127.0.0.1:3307/sharding_db username: sharding password: xxx
六、最终架构总结
1、基础优化的局限性:SQL、索引、数据库参数优化仅能短期续命,无法根治上亿级数据的底层性能瓶颈。
2、Mycat淘汰核心原因:生态停滞、新版技术栈不兼容、SQL兼容性差、运维黑盒,完全不适配现代SpringBoot3、JDK17+项目。
3、双架构落地价值:JDBC保核心业务性能,Proxy保非核心业务运维,取长补短,兼顾性能与可维护性。
4、分层治理核心逻辑:先优化归档、再分片、最后读写分离,非极端硬件瓶颈绝不轻易分库,避免过度设计。
JDBC 做业务读写;Proxy 提供 DBA 查询、报表、数据分析入口;使用同一个配置中心 (Nacos) 统一管理分片规则,两套接入端共用一套分片逻辑
深耕后端生产实战,分享真实线上踩坑、架构演进、MySQL亿级治理、SpringBoot3新版本实战,关注我持续输出落地干货!
欢迎点赞收藏关注,持续更新线上踩坑实录。