Vitess 用 VSchema 描述”哪些表分片、用哪个 vindex 路由”。它是一份 JSON,提交后集群立即生效,无需改业务代码:
{
"sharded": true,
"vindexes": {
"hash": { "type": "hash" }
},
"tables": {
"users": {
"column_vindexes": [
{ "column": "user_id", "name": "hash" }
]
},
"orders": {
"column_vindexes": [
{ "column": "user_id", "name": "hash" }
]
}
}
}
提交命令:vtctldclient ApplyVSchema --keyspace=commerce vschema.json。把 users 和 orders 都用同一个 user_id 哈希路由,可以让”查某用户的所有订单”落在同一分片,避免跨分片 join。
六、VReplication:在线数据迁移与订阅
把存量数据从旧库搬进 Vitess,不用停机。VReplication 通过”全量拷贝 + 增量订阅”双阶段保证一致性,典型用法是 MoveTables 工作流:
# 把 source 库里的 users/orders 搬到 commerce 分片
vtctldclient MoveTables --workflow=commerce2vts \
--target-keyspace=commerce create \
--source-keyspace=source \
--tables='users,orders'
# 观察复制延迟与进度
vtctldclient Workflow --keyspace=commerce show --workflow=commerce2vts
# 校验一致后切换流量
vtctldclient MoveTables --workflow=commerce2vts --target-keyspace=commerce switchtraffic
这套流程让”迁移”从深夜停机窗口变成白天可观测的渐进操作,出问题随时可回退流量。
七、Resharding:业务增长后如何重新分片
当分片逐渐变厚,需要把一个分片切成更多份。Vitess 的 Reshard 同样是声明式、在线的:
# 把原分片 0 切成 -80 与 80- 两个新分片
vtctldclient Reshard --workflow=reshard1 \
--target-keyspace=commerce Create \
--source_shards=0 --target_shards=-80,80-
# 等待新分片追上复制,再逐步切流量
vtctldclient Reshard --workflow=reshard1 --target-keyspace=commerce switchtraffic
# 确认无误后清理旧分片
vtctldclient Reshard --workflow=reshard1 --target-keyspace=commerce cleanup
关键点:新旧分片在切换前并行服务,流量是逐步放的,任何异常都能回滚到旧分片,这才是生产级扩容该有的安全边际。
八、生产落地检查清单
| 检查项 | 要点 |
|---|---|
| 拓扑高可用 | etcd 至少 3 节点;每个分片主从 + 半同步 |
| 备份与 PITR | 定期 vttablet 备份,演练恢复 |
| 慢查询治理 | 监控 scatter query,收敛非分片键查询 |
| 连接数 | 依赖 vttablet 连接池,限制应用直连 |
| 可观测 | 暴露 QPS、复制延迟、路由分布指标 |
| 容量水位 | 单分片行数/体积设阈值告警 |
九、把变更管起来:Schema 迁移与 CI
Vitess 的 Online DDL(基于 VReplication 的 schema 变更)可以避免大表改结构锁表。结合 GitHub Actions 流水线,可以在 CI 中校验 VSchema、跑影子库的迁移演练,再对生产下发,把”改表”也纳入可回滚的工程化流程。
十、总结
Vitess 不是银弹,它用一套运维体系换取了 MySQL 的近乎无限水平扩展能力:vtgate 屏蔽分片、VSchema 声明路由、VReplication 做在线迁移、Reshard 做安全扩容。落地时最该花心思的是分片键设计——选对了,后续扩容顺滑;选错了,scatter query 会反噬性能。对于已经触到单库天花板、又不愿整体迁移到分布式数据库的团队,Vitess 是性价比极高的中间路线。
当单实例 MySQL 在千万级数据和高并发下开始力不从心,垂直升级终有天花板。Vitess 作为承接 YouTube 规模的数据库中间件,用分片(sharding)把数据做水平扩展,分散到成百上千个 MySQL 实例,却让应用像连接单个库一样简单。本文从架构、落地到重新分片,讲清 Vitess 的实战路径。
一、为什么单库扛不住:水平扩展的刚需
读多写少的场景,可以先做主从复制与读写分离(可参考本站 MySQL 主从复制与读写分离实战)来缓解读压力。但一旦写入量、单表行数或连接数持续攀升,单库的物理瓶颈就会显现:磁盘 IO 打满、主从延迟变大、连接风暴拖垮实例。这时继续堆 CPU 和内存的收益急剧递减——你需要的是把数据”切开”,也就是水平扩展。
手工分库分表(如按 user_id 取模路由)初期能跑,但代价藏在细节里:跨分片查询、分布式事务、在线扩容、数据再平衡,每一项都要业务层自己造轮子。Vitess 的价值,正是把这些”分布式数据库的脏活”下沉到中间件,让研发只关心业务逻辑。
那什么时候该认真考虑 Vitess?几条经验信号:单表行数突破千万且仍在高频写入、主库 CPU 长期高于 70%、数据库连接数频繁触碰上限、或者每次改表都要挑深夜低峰窗口。反过来,如果瓶颈只是只读 QPS 高、写入平稳,先做读写分离和缓存通常更划算;只有当”数据量或写入”真的逼近单机天花板,分片才值得引入。过早上分布式,复杂度会反噬团队。
二、Vitess 是什么:在 MySQL 前面加一层”智能代理”
2.1 三大核心组件
- vtgate:无状态查询路由层,应用只连它。它解析 SQL、改写路由、聚合跨分片结果,对上层屏蔽分片细节。
- vttablet:每个 MySQL 实例旁的 Sidecar 代理,负责连接池、查询超时、复制健康检查和备份。
- Topology(topo):用 etcd 或 ZooKeeper 存集群元数据(分片、主从角色、schema),是集群的”大脑”。
2.2 它和 ShardingSphere、MyCat 有什么不同
ShardingSphere 更像” JDBC 层的分片规则”,MyCat 是代理层。Vitess 的差异在于:它把代理、实例管理、在线重分片(Resharding)、数据迁移(VReplication)做成了一套有状态运维体系,而不是只做 SQL 路由。这意味着扩容、迁移这些最危险的操作,可以用声明式工作流安全地跑,而不是停机手工导数据。
三、本地用 Docker Compose 跑起一套最小集群
官方快速上手会拉起 etcd、一组 MySQL + vttablet、vtgate 和 vtctld。核心拓扑如下(具体镜像与启动参数以 Docker Compose 编排 的约定为准):
version: "3"
services:
etcd:
image: vitess/etcd:v3.5.11
mysql-commerce:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
vttablet-commerce:
image: vitess/lite:v20.0.0
command: ["vttablet", "--keyspace=commerce", "--tablet_type=replica"]
vtgate:
image: vitess/lite:v20.0.0
command: ["vtgate", "--cells=zone1", "--cells_to_watch=zone1"]
vtctld:
image: vitess/lite:v20.0.0
command: ["vtctld", "--topo_implementation=etcd2"]
启动后,所有运维操作都通过 vtctldclient 这个统一客户端下发,而不是直接登 MySQL 改结构。
四、分片设计:怎么切、按什么键
4.1 分片键(sharding key)的选择
分片键决定了数据如何分布,也决定了大多数查询能否”单分片命中”。经验法则:选高频等值查询的字段,且基数足够大、分布均匀。典型选择是 user_id、tenant_id、order_id。要避免用会随时间产生热点的字段(如按时间戳范围分片,最新分片会成为写入热点)。
4.2 非分片键查询的代价与应对
当查询条件不含分片键,vtgate 只能把请求广播到所有分片(scatter query)再合并结果。这种查询要尽量少、且控制频率。常见优化:冗余维度表(broadcast table)、把必须的查询列放进分片键组合、或对必须跨分片的报表走异步聚合管道。
| 分片策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 哈希分片 | 分布均匀、无热点 | 范围查询需广播 | 用户、订单类主键 |
| 范围分片 | 范围查询友好 | 易产生写入热点 | 时序、日志类 |
| 租户分片 | 天然隔离、易计费 | 大租户需再切 | SaaS 多租户 |
五、VSchema:声明式定义分片与表路由
Vitess 用 VSchema 描述”哪些表分片、用哪个 vindex 路由”。它是一份 JSON,提交后集群立即生效,无需改业务代码:
{
"sharded": true,
"vindexes": {
"hash": { "type": "hash" }
},
"tables": {
"users": {
"column_vindexes": [
{ "column": "user_id", "name": "hash" }
]
},
"orders": {
"column_vindexes": [
{ "column": "user_id", "name": "hash" }
]
}
}
}
提交命令:vtctldclient ApplyVSchema --keyspace=commerce vschema.json。把 users 和 orders 都用同一个 user_id 哈希路由,可以让”查某用户的所有订单”落在同一分片,避免跨分片 join。
六、VReplication:在线数据迁移与订阅
把存量数据从旧库搬进 Vitess,不用停机。VReplication 通过”全量拷贝 + 增量订阅”双阶段保证一致性,典型用法是 MoveTables 工作流:
# 把 source 库里的 users/orders 搬到 commerce 分片
vtctldclient MoveTables --workflow=commerce2vts \
--target-keyspace=commerce create \
--source-keyspace=source \
--tables='users,orders'
# 观察复制延迟与进度
vtctldclient Workflow --keyspace=commerce show --workflow=commerce2vts
# 校验一致后切换流量
vtctldclient MoveTables --workflow=commerce2vts --target-keyspace=commerce switchtraffic
这套流程让”迁移”从深夜停机窗口变成白天可观测的渐进操作,出问题随时可回退流量。
七、Resharding:业务增长后如何重新分片
当分片逐渐变厚,需要把一个分片切成更多份。Vitess 的 Reshard 同样是声明式、在线的:
# 把原分片 0 切成 -80 与 80- 两个新分片
vtctldclient Reshard --workflow=reshard1 \
--target-keyspace=commerce Create \
--source_shards=0 --target_shards=-80,80-
# 等待新分片追上复制,再逐步切流量
vtctldclient Reshard --workflow=reshard1 --target-keyspace=commerce switchtraffic
# 确认无误后清理旧分片
vtctldclient Reshard --workflow=reshard1 --target-keyspace=commerce cleanup
关键点:新旧分片在切换前并行服务,流量是逐步放的,任何异常都能回滚到旧分片,这才是生产级扩容该有的安全边际。
八、生产落地检查清单
| 检查项 | 要点 |
|---|---|
| 拓扑高可用 | etcd 至少 3 节点;每个分片主从 + 半同步 |
| 备份与 PITR | 定期 vttablet 备份,演练恢复 |
| 慢查询治理 | 监控 scatter query,收敛非分片键查询 |
| 连接数 | 依赖 vttablet 连接池,限制应用直连 |
| 可观测 | 暴露 QPS、复制延迟、路由分布指标 |
| 容量水位 | 单分片行数/体积设阈值告警 |
九、把变更管起来:Schema 迁移与 CI
Vitess 的 Online DDL(基于 VReplication 的 schema 变更)可以避免大表改结构锁表。结合 GitHub Actions 流水线,可以在 CI 中校验 VSchema、跑影子库的迁移演练,再对生产下发,把”改表”也纳入可回滚的工程化流程。
十、总结
Vitess 不是银弹,它用一套运维体系换取了 MySQL 的近乎无限水平扩展能力:vtgate 屏蔽分片、VSchema 声明路由、VReplication 做在线迁移、Reshard 做安全扩容。落地时最该花心思的是分片键设计——选对了,后续扩容顺滑;选错了,scatter query 会反噬性能。对于已经触到单库天花板、又不愿整体迁移到分布式数据库的团队,Vitess 是性价比极高的中间路线。




