ShardingSphere-Proxy 与客户端分片对比
解读
在国内 PHP 面试中,这道题表面问“技术选型”,实则考察候选人是否真正踩过“分库分表”的坑:
- 是否理解两种方案在“连接生命周期、SQL 解析位置、事务边界、升级成本”四条主链路上的差异;
- 能否结合 PHP-FPM 无连接池、Composer 生态、国内云厂商 RDS/DRDS 现状给出权衡;
- 是否具备“灰度切换 + 数据一致性 + 故障排查”落地经验。
如果只答“Proxy 更透明、客户端更快”,会被直接判为“背概念”。
知识点
- PHP-FPM 进程模型:每请求独占一个连接,长连接易被 RDS 断开,连接池需借助 Swoole/WorkerMan 或 Proxy。
- ShardingSphere-Proxy:独立进程,MySQL 协议兼容,PHP 用 PDO 即可连;负责 SQL 解析、路由、归并、读写分离,对业务零侵入。
- 客户端分片(ShardingSphere-JDBC 或 手写):路由逻辑在 PHP 进程内完成,无额外网络 hop,但需引入 PHP 扩展或 Composer 包,升级需全量发版。
- 事务边界:Proxy 支持 XA/Seata 分布式事务;PHP 端分片只能依赖本地事务 + 最终一致补偿,XA 协调器难以下沉到 PHP。
- 国内云环境:阿里云 RDS 只读实例、PolarDB-X(原 DRDS)对 Proxy 协议友好;腾讯云 TDSQL 提供带 Proxy 的接入点,客户端分片需自己适配。
- 监控与排障:Proxy 暴露统一 SQL.log 与 Prometheus 指标;PHP 端分片需埋点,链路追踪(SkyWalking、Zipkin)要手动注入 TraceId。
- 版本升级:Proxy 热升级对业务透明;PHP 分片升级=重新打包 Docker 镜像 + 滚动发布,回滚需数据库层做反向兼容。
- 性能:单次查询 Proxy 多一次 TCP 转发(≈0.3 ms 内网);PHP 端分片节省一次 hop,但 PHP 无协程,并发高时进程数膨胀,内存占用反超。
- 安全:Proxy 集中做 SQL 审计、脱敏;PHP 端分片需每个项目自行过滤,容易遗漏。
- 成本:Proxy 至少 3 节点高可用,增加运维层;PHP 端分片把成本转给开发,需求变更时“人天”成本更高。
答案
“我在 21 年做过一次电商订单中心分库分表,数据量 3 亿,峰值 QPS 1.2 万。最初用 PHP 端分片:基于 shop_id 取模 32 库,每个库 32 表,路由逻辑封装在 Composer 包 shop-sharding。上线后发现三个痛点:
- PHP-FPM 无连接池,每请求新建连接,RDS 连接数被打满,被迫引入 Swoole 连接池,改造周期两周;
- 促销热点导致分片倾斜,需要把模 32 扩容到模 64,PHP 端要同时兼容新旧算法,发版窗口只有 30 分钟,风险极高;
- 财务对账需要跨分片 join,只能在应用层做归并,一次查询 200 ms,接口超时。
后来我们把路由层下沉到 ShardingSphere-Proxy 5.x,三节点部署在 K8s 上,前端 PHP 代码只改一行 host:3307→proxy:3307。升级收益:
- 连接收敛:Proxy 与 RDS 保持 10 条长连接,PHP 侧连接数从 3 万降到 300;
- 在线扩容:Proxy 支持 inline 算法,扩容时只需新增分片并执行 DISTSQL ALTER SHARDING TABLE RULE,业务无需发版;
- 跨分片查询:Proxy 在内存做归并,同样 SQL 耗时降到 40 ms;
- 事务:使用 Seata AT 模式,订单与库存跨库事务由 Proxy 协调,PHP 代码零改造;
- 排障:Proxy 统一输出 slow.log,阿里云 SLS 直接采集,告警规则 5 分钟配完。
当然 Proxy 也有代价:一次查询多一次内网转发,峰值 CPU 增加 8%,但综合人力与稳定性收益,我们评估完全值得。最终这套架构支撑了 22 年双 11,峰值 QPS 2.4 万,P99 延迟 45 ms,全年零故障。
所以,如果团队规模小、请求量低、想快速上线,客户端分片够用;一旦连接数、扩容频率、跨分片需求上来,国内主流做法是‘计算下沉’,用 ShardingSphere-Proxy 让 PHP 回归业务逻辑,是最经济、最可控的方案。”
拓展思考
- 如果公司强制要求“零信任网络”,Proxy 节点与业务 Pod 之间要走 Istio mTLS,如何证明加解密损耗不会成为新瓶颈?
- 当业务用到大量 JSON 字段并依赖 MySQL 8.0 的 JSON_PARTIAL_UPDATE,Proxy 5.5 才支持,上线前如何做灰度验证?
- PHP 8.3 推出 Fiber 后,能否在客户端实现协程级连接池,从而让“客户端分片”重新获得性能优势?
- 国内信创要求数据库替换为 GreatSQL、OpenGauss,Proxy 的 SQL 方言兼容度如何评估?
- 若未来引入 Polardb-X 的 CN 节点自带分片,是否还需要 Proxy?如何设计“双入口”灾备方案?