ShardingSphere实战:用JMeter压测Sharding-JDBC和Proxy,结果有点意外
ShardingSphere性能压测实战:JMeter深度对比Sharding-JDBC与Proxy的隐藏成本
当数据库分片方案成为应对海量数据的标配选择时,ShardingSphere作为国内最成熟的分布式数据库中间件,其两种核心模式——嵌入式SDK(Sharding-JDBC)与独立服务(Sharding-Proxy)的性能差异却鲜有系统性的实测分析。本文将带您用JMeter构建真实业务场景下的压力测试,揭示在分库分表、读写分离、数据脱敏等复杂策略叠加时,两种架构的性能曲线与隐藏成本。
1. 压测环境搭建的艺术
性能测试的第一道门槛往往不是工具使用,而是如何构建贴近真实的生产环境模拟。我们选择四台16核32G云服务器组成集群,每台部署MySQL 8.0.26实例,避免资源争抢导致的测试偏差。网络配置上特别启用10Gbps内网带宽,确保网络IO不成为瓶颈。
测试表结构采用sysbench标准模板扩展,但增加了脱敏字段需求:
CREATE TABLE `pressure_test` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_code` varchar(64) NOT NULL COMMENT '加密存储的用户标识', `amount` decimal(20,4) NOT NULL DEFAULT '0.0000', `mobile_cipher` char(64) NOT NULL DEFAULT '' COMMENT 'AES加密手机号', `id_card_md5` char(32) NOT NULL DEFAULT '' COMMENT '身份证MD5', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user` (`user_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4关键配置细节:在ShardingSphere的加密规则中,我们采用AES-256-GCM算法处理手机号字段,MD5处理身份证字段。这种混合加密策略在实际金融级应用中非常典型。
2. JMeter测试计划设计精要
区别于简单的HTTP压测,数据库中间件测试需要特别关注连接池管理和SQL模板化。我们设计了三层测试结构:
线程组配置
- 20并发线程持续30分钟
- 100ms随机延迟模拟真实用户操作间隔
- 使用CSV Data Set Config循环读取10万条测试数据
JDBC连接管理
// Sharding-JDBC连接配置示例 String jdbcUrl = "jdbc:shardingsphere://classpath:sharding-config.yaml"; HikariConfig config = new HikariConfig(); config.setJdbcUrl(jdbcUrl); config.setMaximumPoolSize(50); config.setIdleTimeout(60000);混合事务设计
- 单路由事务:精确分片键查询+更新
- 跨库事务:分布式主键生成后的关联操作
- 全表扫描:分页查询配合聚合计算
3. 分场景压测数据揭秘
3.1 单路由场景下的王者之争
在10万数据量基础上,我们配置4库×1024表的分片规则。测试结果显示:
| 指标 | Sharding-JDBC | Sharding-Proxy | 原生MySQL |
|---|---|---|---|
| TPS(写入) | 1256 | 892 | 1543 |
| 平均延迟(ms) | 15.2 | 21.8 | 9.7 |
| 99%线(ms) | 38 | 67 | 25 |
意外发现:Proxy在简单查询中额外消耗约30%性能,主要来自协议转换开销。但当启用prepareStatement缓存后,Proxy性能提升40%,与JDBC差距缩小到15%以内。
3.2 主从读写分离的隐藏陷阱
搭建一主三从架构后,我们观察到:
- JDBC模式的读写分离存在粘滞读现象:同一线程内写后立即读可能访问主库
- Proxy的负载均衡算法在高峰时段出现从库热点,需要调整权重策略
- 加密字段检索时,两者性能均下降约25%,因需内存解密结果集
重要提示:在sharding-config.yaml中启用
spring.shardingsphere.props.max.connections.size.per.query=5可显著改善全路由查询性能。
3.3 全路由查询的灾难现场
当执行SELECT COUNT(*) FROM pressure_test WHERE amount>1000这类无法分片的查询时:
- JDBC模式采用串行归并,CPU利用率飙升至90%
- Proxy启动多线程归并,但网络传输量暴增3倍
- 两者响应时间均超过原生MySQL 8倍以上
优化方案:
# 在Proxy配置中增加 props: executor-size: 16 max-connections-size-per-query: 8 sql-show: false4. 性能异常点深度剖析
4.1 连接池管理的魔鬼细节
测试过程中发现,当并发连接超过300时:
- JDBC的HikariCP出现明显的锁竞争
- Proxy的Netty事件循环线程可能成为瓶颈
- 最佳实践是分级连接池配置:
// 分片级别连接池 dataSources: ds_0: maxPoolSize: 50 minIdle: 10
4.2 分布式事务的性能悬崖
在XA事务测试中,Sharding-JDBC的提交耗时随分片数线性增长,而Proxy表现出更好的稳定性:
| 分片数 | JDBC提交耗时(ms) | Proxy提交耗时(ms) |
|---|---|---|
| 2 | 120 | 145 |
| 4 | 280 | 190 |
| 8 | 510 | 230 |
4.3 加密字段的索引失效
由于加密字段无法利用数据库索引,当执行WHERE mobile_cipher=?时:
- JDBC需将所有分片数据拉取到内存解密
- Proxy在服务端解密但传输全部数据
- 建议采用脱敏索引方案:
ALTER TABLE pressure_test ADD COLUMN mobile_prefix CHAR(8) GENERATED ALWAYS AS (SUBSTRING(mobile_cipher,1,8)) STORED; CREATE INDEX idx_mobile_prefix ON pressure_test(mobile_prefix);
5. 架构选型决策树
根据压测结果,我们总结出技术选型的关键维度:
- 延迟敏感型应用:优先选择Sharding-JDBC,其平均延迟降低30-40%
- 多语言技术栈:必须采用Proxy的统一接入层
- 复杂查询场景:Proxy的归并优化更胜一筹
- 云原生环境:Proxy更适合Service Mesh集成
在最后的稳定性测试中,我们意外发现当网络抖动发生时,Proxy的自动重试机制反而导致雪崩效应,而JDBC更快速失败的特性更适合分布式环境。这个反直觉的结论让我们重新审视了"服务化一定更稳定"的固有认知。
