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(恢復時間目標),取決于數據規模。