高可用架構#
MySQL 的高可用架構是生產環境的核心保障。理解主備複製原理和切換策略,是建置可靠資料庫系統的基礎。
主備複製原理#
基本架構#
sequenceDiagram
participant Client as 用戶端
participant M as 主庫 A
participant S as 備庫 B
Client->>M: 用戶端請求
M->>M: 執行 SQL
M->>M: 寫 binlog
M->>S: 傳輸 binlog (io_thread)
S->>S: 寫入 relay log
S->>S: 執行 relay log (sql_thread)複製流程詳解#
- 備庫連接主庫:執行
CHANGE MASTER設定主庫資訊 - 啟動複製執行緒:
START SLAVE啟動 io_thread 和 sql_thread - 主庫發送日誌:主庫讀取 binlog 發送給備庫
- 備庫接收儲存:io_thread 寫入中轉日誌(relay log)
- 備庫執行日誌:sql_thread 解析執行 relay log
雙 M 結構#
flowchart LR
A["節點 A"] <-->|"互為主備<br/>binlog 雙向同步"| B["節點 A'"]
style A fill:#bbdefb
style B fill:#c8e6c9雙 M 結構是 MySQL 高可用中常見的設定:兩個節點互為主備,正常時 A 主 A’ 備,切換後 A’ 主 A 備。最大優勢是切換時不需要修改主備關係,只需切換業務流量。
為避免循環複製,MySQL 使用 server_id 機制:兩個節點的 server_id 必須不同;備庫重放日誌時,生成的 binlog 保留原 server_id;節點收到 server_id 與自己相同的日誌時直接丟棄。
binlog 格式(複製視角)#
binlog 三種格式的完整講解見「04 日誌系統」章。本章直接採用結論:生產環境建議 binlog_format = ROW,原因如下:
- statement 格式在主備使用不同索引時,可能刪除不同的列,導致主從資料不一致
- row 格式記錄被影響列的主鍵,保證備庫複製的結果與主庫一致
- row 格式同時便於誤操作恢復(可從 binlog 反推還原 SQL)
主備延遲#
延遲的定義#
主備延遲 = T3 - T1
T1: 主庫執行完事務的時間
T2: 備庫接收完 binlog 的時間
T3: 備庫執行完事務的時間查看延遲:
SHOW SLAVE STATUS;
-- 關注 seconds_behind_master 欄位延遲的來源#
| 原因 | 解決方案 |
|---|---|
| 備庫機器差(IO/CPU 不足) | 主備對等部署 |
| 備庫壓力大(承載過多查詢) | 一主多從分擔讀 |
| 大事務(單事務執行時間長) | 拆分大事務 |
| 大表 DDL(資料表結構變更耗時) | 使用 gh-ost |
| 並行複製不足(單執行緒執行) | 啟用並行複製 |
大事務是延遲的主要原因之一。主庫事務執行 10 分鐘,備庫就會延遲 10 分鐘。
並行複製#
演進歷程#
MySQL 5.5: 單執行緒複製
↓
MySQL 5.6: 按庫並行
↓
MySQL 5.7: 基於 LOGICAL_CLOCK
↓
MySQL 5.7.22: WRITESET 策略並行複製策略#
| 版本 | 策略 | 並行條件 | 限制 |
|---|---|---|---|
| MySQL 5.6 | 按庫並行 | 不同庫的事務 | 單庫場景無效 |
| MySQL 5.7 | LOGICAL_CLOCK | 同時 prepare 的事務 | 需調整 binlog_group_commit_sync_delay |
| MySQL 5.7.22 | WRITESET | 未修改相同列的事務 | 需額外記憶體維護 writeset |
-- 設定並行複製策略
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
SET GLOBAL slave_parallel_workers = 16;
-- MySQL 5.7.22+
SET GLOBAL binlog_transaction_dependency_tracking = 'WRITESET';主備切換策略#
可靠性優先策略#
1. 等待 seconds_behind_master < 5s
2. 主庫設定 readonly = true
3. 等待 seconds_behind_master = 0
4. 備庫設定 readonly = false
5. 業務切換到備庫特點:
- 有短暫不可用時間
- 保證資料一致性
可用性優先策略#
1. 備庫設定 readonly = false
2. 業務切換到備庫
3. 等待同步完成特點:
- 幾乎無不可用時間
- 可能資料不一致
推薦使用可靠性優先策略。對於資料服務,資料可靠性通常比可用性更重要。
異常切換#
主庫故障時,無法等待延遲歸零:
| 延遲時間 | 影響 |
|---|---|
| 很小 | 快速切換,影響小 |
| 較大 | 要麼等待(不可用),要麼立即切換(可能丟資料) |
減少主備延遲是提高可用性的關鍵。延遲越小,切換越快,可用性越高。
GTID 模式#
什麼是 GTID#
GTID(Global Transaction Identifier)= server_uuid:gno
- server_uuid:執行個體的唯一識別
- gno:事務序號,每次提交遞增
GTID 的優勢#
傳統位點方式的問題:
CHANGE MASTER TO
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
-- 需要手動計算位點,容易出錯GTID 方式:
CHANGE MASTER TO
MASTER_AUTO_POSITION=1;
-- 自動找到正確的同步位置啟用 GTID#
-- my.cnf
gtid_mode = ON
enforce_gtid_consistency = ONGTID 的工作原理#
- 備庫把自己的 GTID 集合發給主庫
- 主庫計算差集,找出備庫缺少的事務
- 從第一個缺失事務開始發送 binlog
- 自動處理主備切換,無需手動找位點
一主多從架構#
架構圖#
flowchart TB
M["主庫 A"]
M -->|binlog| S1["備庫 A'"]
M -->|binlog| S2["從庫 B"]
M -->|binlog| S3["從庫 C"]
style M fill:#fff3e0
style S1 fill:#c8e6c9
style S2 fill:#e3f2fd
style S3 fill:#e3f2fd主庫故障切換#
使用 GTID 模式時,從庫只需執行:
CHANGE MASTER TO
MASTER_HOST='new_master_ip',
MASTER_AUTO_POSITION=1;
START SLAVE;系統自動計算同步位點,大大簡化了切換流程。
最佳實踐#
參數設定#
-- binlog 格式
binlog_format = ROW
-- 啟用 GTID
gtid_mode = ON
enforce_gtid_consistency = ON
-- 並行複製
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 16
-- 備庫唯讀
read_only = 1監控指標#
| 指標 | 說明 | 告警閾值 |
|---|---|---|
| seconds_behind_master | 主備延遲秒數 | > 30s |
| Slave_IO_Running | IO 執行緒狀態 | != Yes |
| Slave_SQL_Running | SQL 執行緒狀態 | != Yes |
備庫設定唯讀的原因#
- 防止誤操作
- 防止切換時雙寫
- 用於判斷節點角色
readonly 對 super 權限使用者無效,複製執行緒可以正常執行。
本章小結#
| 主題 | 要點 |
|---|---|
| 複製原理 | io_thread 接收,sql_thread 執行 |
| binlog 格式 | 推薦 row,資料一致且可恢復 |
| 主備延遲 | 大事務、單執行緒複製是主因 |
| 並行複製 | 5.7.22 WRITESET 效果最好 |
| 切換策略 | 可靠性優先,減少延遲 |
| GTID | 自動位點,簡化切換 |
高可用的關鍵是減少主備延遲。延遲越小,切換越快,RPO 和 RTO 都更優。