Vitess:云原生 MySQL 水平扩展集群
简介
Vitess 是一个用于部署、扩展和管理大型开源数据库实例集群的数据库解决方案。它最初为 YouTube 而构建,现已被 Cloud Native Computing Foundation (CNCF) 接受为毕业项目。Vitess 将许多重要的 MySQL 特性与 NoSQL 数据库的可扩展性相结合,能够对数据进行分析片、分片管理、连接池、查询重写等操作,让您的应用程序就像在操作一个单一的逻辑数据库一样。
简单来说,Vitess 是 云原生的 MySQL 水平扩展集群。它让您能够像使用单机 MySQL 一样使用一个可以水平扩展的数据库。
为什么需要 Vitess
当单体 MySQL 数据库在数据量或读写压力上达到瓶颈时,常见的垂直扩展(升级硬件)成本高昂且有上限。水平扩展(分库分表)虽然能解决容量问题,但会给应用层带来巨大的复杂性:需要感知分片键、处理跨分片查询、维护连接池、执行模式变更等。
Vitess 正是为了解决这些痛点而生,它提供了:
- 透明的分片能力:应用无需关心数据被存储在哪个分片上,通过标准 SQL 即可访问。
- 连接池与复用:内置连接池,可将数千个应用连接合并为少量 MySQL 连接,保护数据库免受过载。
- 在线模式变更:通过与
gh-ost或pt-online-schema-change集成,在不锁表的情况下执行 DDL。 - 故障恢复与重定向:内置守护进程与拓扑管理,检测到故障后可快速重定向流量,保证高可用。
- 监控与可观测性:提供丰富的状态页面和
/debug/vars端点,易于集成 Prometheus 等监控系统。 - 云中立的部署:可以运行在 Kubernetes、裸机或任何云平台上。
核心概念
在学习 Vitess 之前,您需要理解几个关键术语:
Cell(单元)
Cell 是一个故障隔离域,通常对应一个数据中心或可用区。一个 Vitess 集群可以跨多个 Cell 部署,以实现地理分布式部署。每个 Cell 内可以包含多个 Tablet。
Keyspace(键空间)
Keyspace 是 Vitess 中的逻辑数据库,类似于 MySQL 中的数据库(database)。一个 Keyspace 可以包含多个分片。对于未分片的 Keyspace,所有数据都位于单个分片中。
Shard(分片)
分片是 Keyspace 中的数据分区。一个分片通常包含一个 MySQL 复制集(一主多从)。数据根据分片键和分片策略(哈希或范围)分布到不同的分片中。
Tablet(平板)
Tablet 是 Vitess 中最小的数据管理单元,它代表一个运行中的 mysqld 实例,并由 vttablet 进程进行管理。每个 Tablet 被赋予一种类型:
- master(主):当前接受写入操作的 Tablet。
- replica(从):用于读取操作,可能从主节点异步复制。
- rdonly(只读):用于离线处理、分析查询等,也参与复制。
VTGate
VTGate 是一个轻量级的无状态代理,应用程序连接到此服务并通过它发送查询。它负责将 SQL 查询路由到正确的分片,并进行结果聚合。VTGate 对外呈现为单一的 MySQL 服务器端点。
VTTablet
VTTablet 是运行在每个 MySQL 实例旁的控制代理。它执行查询、管理连接池、进行权限检查、向拓扑服务上报状态,并与 VTGate 协同工作。
Topology Service(拓扑服务)
拓扑服务(如 etcd、ZooKeeper、Consul)存储了集群的所有元数据:Keyspace 和 Shard 定义、Tablet 的状态、主从关系等。所有的 Vitess 组件都从拓扑服务读取和更新元信息。
VTAdmin
VTAdmin 是一套用于管理和查看 Vitess 集群的 Web UI 和 API。它让您可以查看拓扑、执行紧急故障转移、启动重新分片任务等。
架构概览
一个典型的 Vitess 部署包括以下组件:
应用程序
|
VTGate (无状态代理,可多实例)
|
拓扑服务 (etcd/consul 等)
|
+---------+---------+
| Cell A | Cell B |
| | |
| VTTablet | VTTablet |
| + MySQL | + MySQL |
| VTTablet | VTTablet |
| + MySQL | + MySQL |
+------------------+------------------+
- 数据平面:VTGate 将 SQL 路由到正确的 VTTablet,VTTablet 将 SQL 转发给 MySQL。结果沿原路返回。
- 控制平面:VTTablet 向拓扑服务注册并上报健康状态。VTAdmin、VTOrc(协调器)等组件基于拓扑信息进行故障恢复、重分片等操作。
查询流程:
- 应用连接到 VTGate(通常使用 MySQL 协议)。
- VTGate 解析 SQL,根据分片键确定需要访问哪些分片。
- VTGate 向相关 VTTablet 发送请求。
- VTTablet 执行查询,可能利用连接池,最终将结果返回给 VTGate。
- 对于需要跨分片聚合的查询,VTGate 进行合并后返回给应用。
快速上手:部署一个简单的 Vitess 集群
以下步骤将引导您在本地使用 docker-compose 启动一个 Vitess 集群,体验基本的分片操作。本示例基于 Vitess 官方示例。
前提条件
- 安装 Docker 与 Docker Compose
- 安装 MySQL 客户端(用于测试连接)
步骤 1:克隆 Vitess 仓库并进入示例目录
git clone https://github.com/vitessio/vitess.git
cd vitess/examples/compose
步骤 2:启动集群
docker-compose up -d
此命令会启动拓扑服务(etcd)、VTGate、VTTablet 和一个未分片的 Keyspace(名为 commerce)。可能需要几分钟下载镜像。
步骤 3:验证环境
# 检查容器运行状态
docker-compose ps
# 进入 VTGate 容器,连接 MySQL 协议端口
docker-compose exec vttablet101 mysql -u root -h vttablet101 -P 3306
在 MySQL 客户端中,您应该能看到 commerce 数据库。
步骤 4:创建分片 Keyspace 并插入数据
我们将创建一个名为 customer 的 Keyspace,采用哈希分片,并分成两个分片:
# 使用 vtctld 命令创建 Keyspace
docker-compose exec vtctld vtctldclient CreateKeyspace customer --durability-policy=semi_sync
# 创建分片定义:使用 - 表示分片范围,对哈希分片通常用 -80, 80- 表示两个分片
docker-compose exec vtctld vtctldclient ApplyVSchema --vschema='{
"sharded": true,
"vindexes": {
"hash": {
"type": "hash"
}
},
"tables": {
"customer": {
"column_vindexes": [
{
"column": "customer_id",
"name": "hash"
}
]
}
}
}' customer
# 创建两个分片 tablet(-80 和 80-)
# 以下示意使用本地示例脚本,实际操作可参考:https://vitess.io/docs/get-started/local/
# 为简化,我们直接使用 compose 内置的已有分片示例。官方 compose 示例通常已预置了 `customer` 分片。
如果使用预置的 compose 示例,启动后应存在 customer keyspace 及其两个分片。
步骤 5:通过 VTGate 访问分片表
使用 MySQL 客户端连接 VTGate(端口 15306):
mysql -h 127.0.0.1 -P 15306 -u user
在 MySQL 终端中执行:
USE customer;
CREATE TABLE customer (
customer_id bigint NOT NULL,
email varbinary(128),
PRIMARY KEY (customer_id)
);
-- 插入几条数据,customer_id 会被哈希到不同分片
INSERT INTO customer (customer_id, email) VALUES (1, 'alice@domain.com');
INSERT INTO customer (customer_id, email) VALUES (2, 'bob@domain.com');
INSERT INTO customer (customer_id, email) VALUES (3, 'charlie@domain.com');
-- 查询,Vitess 会路由到正确分片
SELECT * FROM customer WHERE customer_id = 2;
-- 跨分片全表扫描(适用于小表)
SELECT * FROM customer;
此时您已经体验了 Vitess 的基本分片路由能力。
使用 Vitess 的关键实践
分片键选择
- 选用高基数的列,如用户 ID、订单 ID。
- 避免选择会导致数据倾斜的列(如状态字段)。
- 推荐使用
hashvindex(虚拟索引)以均匀分布数据。
避免跨分片查询
- 设计数据模型时,尽量让关联数据落在同一分片(通过分片键)。
- 对于必须跨分片聚合的场景,Vitess 支持
GROUP BY、ORDER BY的分散查询,但性能会受影响。
连接池管理
- VTGate 与 VTTablet 之间以及 VTTablet 与 MySQL 之间都有连接池,您只需关注应用端连接 VTGate 的配置。
- VTGate 是无状态的,可以通过水平扩展来增加并发处理能力。
模式变更
- 使用
vtctldclient ApplySchema执行 DDL,它会与 Vitess 集成的在线变更工具协作,避免锁表。 - 注意:某些复杂 DDL 操作仍需谨慎规划。
监控与告警
- 每个 Vitess 组件都导出 Prometheus 指标,可借助 Grafana 仪表盘进行可视化。
- 关注指标:
Vtgate查询延迟、错误率、VTTablet 复制延迟、连接池使用率。
总结
Vitess 将 MySQL 从单体架构中解放出来,使其具备像 NoSQL 系统一样的水平扩展能力,同时保留了完整的 SQL 支持和 ACID 事务。通过透明的分片、连接池、内置高可用和在线变更,Vitess 成为云原生数据库管理的理想选择,尤其适合需要处理海量数据和高并发的互联网应用。
想要深入了解更多高级特性,如重分片(resharding)、物化视图、VReplication 等,请查阅 Vitess 官方文档。现在您已经迈出了第一步,可以尝试在开发环境中实践更复杂的部署模式。