MySQL 是Uber数据基础设施的核心支柱,支撑着平台上大量关键操作。Uber 拥有一套庞大的 MySQL 集群,如何构建一个控制平面来管理如此大规模的 MySQL 集群,并同时确保零宕机、零数据丢失是一个十分有挑战性的问题。下面重点介绍 Uber 的 MySQL 集群架构、控制平面的操作机制,以及近年来在控制平面上的关键改进。
一、架构概览
1.1 概览
Uber 的 MySQL 集群由多个集群(官方数据称包含超过 2300 个独立的集群)组成,每个集群包含若干节点。系统包含两个主要的数据流:
-
数据面(Data Plane):服务端/客户端与 MySQL 集群交互。托管在 K8s中的无状态服务通过标准 JDBC 客户端连接至其对应的 MySQL 集群。每台服务器上部署了一个反向代理,用于基于角色(主节点/副本/批处理)存储并维护路由映射。这使客户端能根据查询内容发现并连接到合适的节点。
-
控制面(Control Plane):负责集群和节点的创建、维护与下线,并确保安全策略合规,以及与公司内部基础设施的集成。
Uber 的 MySQL 架构由以下几个关键组件构成:
- 控制面(Control Plane)
- 数据面(Data Plane)
- 服务发现面(Discovery Plane)
- 可观测性系统(Observability)
- 变更数据捕获 & 数据仓库同步(CDC & DW Ingestion)
- 备份与恢复系统(Backup/Restore)
1.2 控制平面(Control Plane)
MySQL 控制平面是一个基于状态的系统,由多个服务和存储组件构成。其中最核心的组件是 技术管理器(Technology Manager),负责协调控制平面内其他模块的操作。它的关键职责如下:
- 发布目标状态(Goal State)至 Odin(Uber 内部用于有状态服务管理的基础平台)。目标状态包括资源配置、节点数量、节点角色(主/从)、数据节点需要运行的边车容器、MySQL 服务设置(如 binlog 格式、SQL 模式)等内容。
- 控制平面会持续保证每一个集群与节点都趋于其目标状态,确保系统始终处于一致性配置。
此外,技术管理器还支持通过 工作流(Workflow) 修改系统状态。这些工作流是基于 Cadence 的容错、持久化、长生命周期的自动化任务,例如:
- 为现有集群添加节点;
- 主节点故障转移(Failover);
- 修改节点上的 MySQL 参数;
- 更换副本的主库节点等。
其他核心职责还包括:
- 集群管理:创建、更新与删除集群;
- 主库故障转移:切换集群的主节点;
- 节点生命周期管理:增删改替服务器节点;
- 节点均衡调度:向 Odin 的调度引擎提供信号,确保节点在地理位置上的均衡分布,提高容灾能力;
- 数据库操作:系统变量设置、主从复制配置、弹性扩缩容等操作。
过去控制平面与底层基础设施耦合度较高,导致 MySQL 故障经常影响资源调度。这种耦合影响了 60 多种工作流的稳定性,最终推动了整个控制平面的重构。
1.3 控制器(Controller)
控制器作为所有MySQL集群的外部观察者,持续监听 MySQL 集群的状态信号,并在违反预设规则时执行自恢复操作。控制器的核心职责包括:
- 监控主节点健康状况;
- 在发现主节点不可用时自动触发 主库故障转移(Failover);
- 在 Group Replication 环境中,确保集群状态均衡。
二、关键流程编排机制
控制平面主要通过 工作流机制 与外部交互。工作流是异步事件驱动的任务序列,支持复杂操作的编排和错误恢复。整套工作流系统基于 Cadence
构建,实现高可用、高容错的流程控制。
以下是两个关键流程的架构介绍。
2.1 主节点故障转移(Primary Failover)
Uber 使用 单主多从 架构,主节点处理写操作,使用 MySQL 的 Binlog 将数据同步到多个副本。
控制器根据主节点健康状态,自动执行以下两种故障转移:
- 正常转移(Graceful Failover):例如运维过程中主节点需下线或重启。流程如下:
- 将当前主节点设置为只读;
- 停止主节点流量;
- 选择新主节点(优先选择当前数据中心延迟最小的副本);
- 等待新主节点应用所有 Binlog;
- 启用新主节点写入功能。
- 故障转移(Emergency Failover):不依赖原主节点的数据同步,适用于主节点已不可达的场景。例如数据中心宕机、主节点失联。
主故障转移是保证下游服务99.99%的可用性这一SLA的关键过程。
2.2 节点替换(Node Replacement)
节点替换意味着将 MySQL 节点及其数据从一台主机迁移至另一台,同时确保客户端无感知。替换流程主要包括两个操作:
- 节点添加:确定目标主机 → 安装 MySQL → 数据同步(首选主节点);
- 节点移除:处理依赖(复制关系等)后,安全下线旧节点。
注意事项:
- 新节点需具备相同硬件配置;
- 放置在相同容灾等级的主机;
- 若旧节点是复制父节点,其子节点必须指向新的替换节点或连接到集群中的另一个节点。
- 若旧节点是主库,需先执行优雅主库切换。
2.3 架构变更(Schema Changes)
Uber 支持通过自助工作流自动执行 无锁的在线表结构变更。根据变更类型和数据规模,系统根据模式更改类型和数据大小智能地选择模式应用策略:
- MySQL Instant Alter;
- Percona 的 pt-online-schema-change 工具(ptosc)。
支持 Dry-Run 模式:先在隔离副本上执行变更,确保安全后再在主库生效。
此外,表结构变更还集成到了 CI/CD 流水线中,开发者将变更写入 schema 文件,与代码一起提交,审核通过后自动触发部署,确保数据库结构与业务代码一致。
三、数据面(Data Plane)
一个运行中的 MySQL 节点由多个容器构成,部署在同一宿主机上,容器间通过 Docker 网络通信。
- 数据库容器:运行 mysqld 进程,默认使用 InnoDB 引擎;
- Worker 容器:收敛当前状态至目标状态,这将MySQL节点与Odin放置引擎集成在一起;
- 监控容器:收集 QPS、锁等待、连接数等指标;
- 健康探测器:周期性检测主节点状态,供控制器做出自动化响应;
- 备份容器(Backup):周期性拉起,获取数据库备份并将其上传到对象存储,
四、发现平面(Discovery Plane)
为了简化客户端与MySQL集群的交互,路由平面或发现平面提供了对不断变化的硬件基础设施的抽象。为服务连接到其MySQL集群提供了一个单一的虚拟IP,隐藏了硬件级别的所有更改。路由发现平面由以下三个主要模块组成:
- 反向代理:充当负载均衡器,转发请求;
- 连接池服务:在节点状态变化时更新代理配置;
- 标准客户端库:提供连接创建、连接池管理、超时控制、度量采集等能力。
路由层使用 etcd 作为强一致性的拓扑存储。所有拓扑变更通过 etcd watch 机制通知连接池服务,动态调整反向代理配置,实现读写流量智能调度。发现平面支持禁用特定节点上的流量。这对于调试MySQL节点中的任何硬件或软件故障而不影响客户流量非常有用。
五、可观测性(Observability)
系统通过监控容器和探测器持续采集指标,并发送至 Uber 的日志与指标平台。支持的告警项包括:
- 写不可用;
- 主从延迟;
- CPU 使用率过高;
- 异常连接数等。
开发团队和上游服务都可订阅这些告警,第一时间发现异常,保障服务可靠性。
六、变更数据捕获(CDC)
MySQL 集群通过 Storagetapper 实现 CDC,实时捕捉 binlog 中的insert, update和delete操作,并流式传输至 Apache Kafka,再写入 Apache Hive数据仓库。系统支持上游结构变更、数据转换及格式转换等操作。
七、备份与恢复(Backup & Restore)
Uber 的 MySQL 集群支持完全自动化的备份与恢复,基于 Percona XtraBackup 实现。支持:
- 4 小时的 RPO(恢复点目标);
- 分钟到小时级的 RTO(恢复时间目标),取决于数据规模。