Uber的MySQL实践(一)——学习笔记

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),负责协调控制平面内其他模块的操作。它的关键职责如下:

  1. 发布目标状态(Goal State)至 Odin(Uber 内部用于有状态服务管理的基础平台)。目标状态包括资源配置、节点数量、节点角色(主/从)、数据节点需要运行的边车容器、MySQL 服务设置(如 binlog 格式、SQL 模式)等内容。
  2. 控制平面会持续保证每一个集群与节点都趋于其目标状态,确保系统始终处于一致性配置。

此外,技术管理器还支持通过 工作流(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) :例如运维过程中主节点需下线或重启。流程如下:
    1. 将当前主节点设置为只读;
    2. 停止主节点流量;
    3. 选择新主节点(优先选择当前数据中心延迟最小的副本);
    4. 等待新主节点应用所有 Binlog;
    5. 启用新主节点写入功能。
  • 故障转移(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(恢复时间目标),取决于数据规模。
相关推荐
0wioiw07 分钟前
Redis(④-消息队列削峰)
数据库·redis·缓存
Runing_WoNiu21 分钟前
Mysql与Ooracle 索引失效场景对比
数据库·mysql·oracle
bobz96524 分钟前
QT designer 常用技巧
后端
shi578327 分钟前
C# 常用的线程同步方式
开发语言·后端·c#
beijingliushao31 分钟前
32-Hive SQL DML语法之查询数据
数据库·hive·sql
没逻辑1 小时前
抗量子密码技术(PQC)演变
后端·量子计算
JIngJaneIL1 小时前
专利服务系统平台|个人专利服务系统|基于java和小程序的专利服务系统设计与实现(源码+数据库+文档)
java·数据库·小程序·论文·毕设·专利服务系统平台
day>day>up1 小时前
django uwsgi启动报错failed to get the Python codec of the filesystem encoding
后端·python·django
__风__1 小时前
windows 上编译PostgreSQL
数据库·postgresql
Livingbody2 小时前
FastMCP In Action跑通第一个MCP之跟学python版
后端