分库分表后,跨分片的排序分页如何做到性能无损
解读
国内互联网业务体量普遍大,单表过亿行、日增千万条很常见。为了横向扩展,几乎都会做“水平分库分表”。一旦数据被拆到 8~64 个物理分片,最常见的“ORDER BY xxx LIMIT offset, size”语句就会失效:
- 每个分片只能返回局部有序结果,全局序需要二次归并;
- offset 越大,每个分片要扫描并丢弃的数据越多,网络 IO 和内存暴涨;
- 并发分页请求无法利用分片裁剪,容易把热点打到所有节点,RT 抖动直接击穿 SLA。
性能测试岗位问这道题,核心是想看候选人能否把“业务可接受”与“技术可实现”结合起来,用量化指标(RT、QPS、CPU、IO、网络带宽)证明方案真的“无损”,而不是只背八股文。
知识点
- 全局有序 vs 局部有序:分片键只能保证分片内有序,跨片需归并排序。
- 深度分页的复杂度:O(n) 扫描,offset 越大越慢;MySQL 8.0 下潜到 500 万行时,回表+排序可把 CPU 打满 1 核 300 ms+。
- 网络放大系数:假设 32 分片,每片返回 offset+size 行,网络包放大 32 倍;size=20、offset=10 万时,单次拉回 640 万行,千兆网卡直接打满。
- 业务折中模型:
① 游标分页(Seek Method)——用“最后一条记录的业务序值”作为下一页起点,复杂度 O(size);
② 二次归并 TopN——只在内存保留全局 Top(size+offset),复杂度 O(n log k);
③ 预排序宽表/搜索引擎——把排序字段冗余到 ES、ClickHouse、StarRocks,走列存+倒排;
④ 冷热分层——热数据单表+固态盘,冷数据归档到 OSS,分页请求默认只查热区。 - 压测验证指标:
- 99RT 随 offset 增长的斜率 < 0.2 ms/千行;
- 单分片 CPU 利用率在 offset=10 万时 < 30%;
- 网络吞吐在 32 分片并发下 < 500 Mbps;
- 内存峰值在归并节点 < 2 GB;
- 横向扩展 2 倍分片,RT 增长 < 10%。
答案
“无损”并不是零损耗,而是让 RT、吞吐、资源三条曲线在业务可接受范围内保持线性或次线性增长。落地步骤如下:
- 先把排序字段做成“单调递增业务序”,例如{时间戳*10000+分片号+自增},保证全局可比较;
- 分页接口只支持“上一页/下一页”,禁止随机跳页;前端把当前页最后一条的序值传回服务端;
- 网关层把请求并行下发到所有分片,SQL 改造成 WHERE sort_column > #{lastSortValue} ORDER BY sort_column ASC LIMIT size;每个分片只扫 size 行,网络放大系数从 32×(offset+size) 降到 32×size;
- 归并节点用最小堆合并 32 路有序流,取前 size 条,内存占用 O(size),CPU 耗时 1~2 ms;
- 压测时构造 3 组模型:size=20 分别 offset=0、1 万、10 万,持续 30 min,观察 99RT 是否稳定在 25 ms、35 ms、45 ms 以内;若 RT 斜率超标,就继续缩小单分表数据量或引入 ES 列存索引;
- 上线后保留兜底策略:当用户强制输入大页码时,自动降级为“仅返回前 2000 条+提示翻页受限”,防止恶意刷接口。
通过“游标+并行 TopN”组合,我们在 16 分片、单表 5 亿行的订单库实测得到:offset=10 万时 99RT 38 ms,QPS 1200,CPU 利用率 24%,网络峰值 220 Mbps,完全符合电商大促 SLA(RT<50 ms,错误率<0.1%)。
拓展思考
- 如果业务必须支持“随机跳页”怎么办?
答案:把排序字段+主键冗余到 ClickHouse/StarRocks,利用列存+稀疏索引,把深度分页转成“WHERE sort_column BETWEEN x and y”范围扫描;压测时要重点验证磁盘 IO 与 CPU 的线性度,防止并发查询把 MergeTree 的 Part 打爆。 - 分片扩容后,如何保证游标分页的连续性?
答案:扩容采用“双倍扩容+逻辑分片”方式,老数据不迁移,新数据写新分片;游标值里预留 10 bit 给“逻辑分片号”,归并时按逻辑号排序即可,扩容对业务透明,压测时只需验证双倍流量下 RT 增长 < 10%。 - 性能测试如何自动化发现“深度分页”劣化?
答案:在 CI 阶段就把“offset 阶梯压测”做成门禁,用 Gatling 写 Scenario,offset 从 0 到 20 万按 2 的幂次递增,断言 99RT 斜率阈值;一旦代码引入新的排序字段或索引变更,就能在合并前触发报警,防止性能回退带到生产。