需求背景
目前的服務跑在 Vultr Regular Performance VPS 上,隨著流量成長與運算需求提升,決定升級至 High Performance 或 Optimized Cloud Compute 機型。然而這套系統有幾個特性讓遷移不能草率進行:
- 系統持續有使用者流量,幾乎所有 request 都會觸發資料庫寫入
- 使用 MariaDB 作為主要資料庫
- 不能接受長時間停機
- 必須確保資料一致性,不允許雙寫導致資料分裂
這不是一台純靜態網站的搬家——任何瞬間都可能有資料正在寫入,所以遷移策略的核心問題是:如何在不丟資料的前提下,把停機時間壓到最短?
本案例為多個服務與資料庫在同一台主機上,若資料庫與服務是分開的,遷移策略會有些微不同。一般也建議將資料庫與服務分開部署。
為什麼不能直接切 DNS?
最直覺的做法是在新機器部署好之後直接修改 DNS A Record。但 DNS 存在 propagation 延遲——修改後全球各地的 DNS cache 不會同步更新,可能需要數分鐘到數小時才能完全生效。
在這段過渡期內,部分使用者的請求會被導向舊主機,部分則會進入新主機。如果兩邊都允許寫入,就會發生:
- 資料分裂:同一筆業務邏輯的資料分散在兩台機器
- Session 不一致:使用者登入狀態在新舊主機之間無法共享
- Queue / Cache 異常:任務被重複消費或遺失
- 上傳檔案不同步:圖片或附件只存在於其中一台
結論很明確:新舊主機不能同時對外提供正式寫入服務。需要一個機制確保切換瞬間只有一台在服務。
遷移策略:MariaDB Replication + 短暫維護模式
業界對這類有狀態服務遷移的標準做法是 先同步、後切換:
- 新主機在背景持續從舊主機同步資料
- 確認同步完成後,短暫停止舊主機的寫入
- 等待最後一筆資料同步完畢
- 將 DNS 指向新主機,新主機正式接手
這個策略的關鍵在於:大量的資料同步工作都在正式切換之前完成,使用者完全無感。真正需要停機的只有最後「停止寫入 → 追平 → 切換」這幾秒鐘。
MariaDB Replication 的運作原理
MariaDB Replication 基於 binary log(binlog)機制:
- 舊主機(Master)的所有寫入操作都會記錄到 binlog
- 新主機(Replica)持續讀取 Master 的 binlog 並重放(replay)這些操作
- Replica 的資料幾乎即時與 Master 保持一致
整個 replication 過程中,舊主機正常服務、使用者正常使用,完全不受影響。
完整操作步驟
Step 1:建立 Snapshot
在 Vultr 控制台對舊 VPS 建立 Snapshot。這一步有兩個目的:
- 快速複製環境:新主機可以直接從 Snapshot 建立,省去重新安裝與設定的時間
- 保留 Rollback 能力:萬一遷移過程出問題,可以隨時回復
Step 2:建立新 VPS
在 Vultr 控制台建立新的 VPS,注意幾個要點:
- 選擇目標機型(High Performance / Optimized Cloud Compute)
- 使用剛才建立的 Snapshot 作為系統映像
- Region 盡量與舊機一致,降低 replication 延遲
Step 3:驗證新主機環境
由於是從 Snapshot 建立,大部分服務應該已經就位,但仍需逐一確認:
| 項目 | 確認內容 |
|---|---|
| Web Server | Nginx/Apache 是否正常啟動、站台設定是否正確 |
| MariaDB | 服務是否啟動、資料是否完整 |
| Cron | 排程任務是否正確載入 |
| Firewall | UFW / iptables 規則是否與舊機一致 |
| SSL | 憑證是否有效(Snapshot 複製過來的憑證可能需要重新簽發) |
| Disk Mount | 如有額外掛載磁碟,確認 mount point 正確 |
注意:此時新主機的 Web Server 應該保持關閉或僅允許內部存取,避免外部流量意外進入。
Step 4:建立 MariaDB Replication
這是整個遷移的核心步驟。
舊主機(Master)設定
編輯 MariaDB 設定檔(通常為 /etc/mysql/mariadb.conf.d/50-server.cnf),加入:
[mysqld]
server-id = 1
log_bin = mysql-bin重啟 MariaDB 後,建立 replication 專用帳號:
CREATE USER 'repl'@'新主機IP' IDENTIFIED BY '強密碼';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'新主機IP';
FLUSH PRIVILEGES;查看目前的 binlog 位置,後續 Replica 需要用到:
SHOW MASTER STATUS;
-- 記下 File(如 mysql-bin.000003)和 Position(如 785)新主機(Replica)設定
編輯 MariaDB 設定檔,設定不同的 server-id:
[mysqld]
server-id = 2重啟 MariaDB 後,指定 replication 來源並啟動同步:
CHANGE MASTER TO
MASTER_HOST = '舊主機IP',
MASTER_USER = 'repl',
MASTER_PASSWORD = '強密碼',
MASTER_LOG_FILE = 'mysql-bin.000003',
MASTER_LOG_POS = 785;
START SLAVE;確認同步狀態:
SHOW SLAVE STATUS\G關鍵欄位:
Slave_IO_Running: Yes— IO 執行緒正常連線Slave_SQL_Running: Yes— SQL 執行緒正常重放Seconds_Behind_Master: 0— 已完全追平,無延遲
Tip:如果
Seconds_Behind_Master持續大於 0,可能是網路延遲或新主機效能不足。在正式切換前,必須等到這個值穩定為 0。
Step 5:提前降低 DNS TTL
在正式切換前 至少 1~2 小時,將 DNS TTL 調低至 60~300 秒。這樣做的目的是讓各地 DNS cache 更快過期,縮短切換後的 propagation 時間。
如果原本 TTL 是 3600 秒(1 小時),你至少需要等 1 小時讓舊的 cache 過期後,新的低 TTL 才會全面生效。
Step 6:正式切換(唯一的短暫停機)
這是整個遷移中真正影響服務的階段,目標是將時間控制在 數秒到數分鐘 以內。
6-1. 舊主機進入維護模式
停止應用層的寫入——可以透過 Nginx 返回 503 維護頁面,或在應用層啟用 maintenance mode。
重點:Nginx 和 MariaDB 本身不要停止,因為 replication 仍需要繼續運作。
6-2. 等待 Replica 完全追平
在新主機上確認:
SHOW SLAVE STATUS\G
-- 確認 Seconds_Behind_Master: 0此時新舊資料庫的資料完全一致。
6-3. 停止 Replication,新主機升格為 Master
STOP SLAVE;
RESET SLAVE ALL;執行完畢後,新主機不再是任何人的 Replica,正式成為獨立的 Master。
Step 7:切換 DNS
將 A Record 指向新主機的 IP。由於 Step 5 已經降低了 TTL,大部分使用者會在數分鐘內被導向新主機。
Step 8:新主機正式上線
此時的流量分佈:
- 已更新 DNS 的使用者 → 進入新主機,正常使用
- 仍持有舊 DNS cache 的使用者 → 進入舊主機,看到維護頁面
因為舊主機已經進入維護模式、不接受寫入,所以不會發生雙寫問題。使用者最多看到一個維護頁面,等 DNS cache 過期後自動切換到新主機。
Step 9:觀察與驗證
切換後建議至少觀察 30~60 分鐘,確認以下項目正常:
- HTTP 回應正常(狀態碼、回應時間)
- 資料庫讀寫正常
- API 回應正確
- 排程任務正常執行
- SSL 憑證有效
建議保留舊主機至少一天,作為緊急 rollback 的備案。
Step 10:收尾
確認一切穩定後:
- 恢復 DNS TTL 至正常值(如 3600 秒)
- 關閉或銷毀舊 VPS
- 清理不再需要的 Snapshot(可選,保留一段時間更安全)
- 清除新主機上 replication 相關設定(
server-id可保留,但 replication user 可移除)
為什麼這個方案停機時間極短?
因為整個流程中,最耗時的資料同步工作都是在 服務正常運行期間 完成的。Replication 從建立到追平可能需要數分鐘到數小時(取決於資料量),但這段時間使用者完全無感。
真正需要停止服務的只有三個動作:
- 舊主機進入維護模式(瞬間)
- 等待 Replica 追平最後幾筆資料(通常數秒)
- 切換 DNS(瞬間)
加總起來,實際停機時間通常在 10 秒到 5 分鐘之間。
真正零停機為何困難?
如果連這幾秒的維護模式都不能接受,就需要更複雜的基礎設施:
| 方案 | 用途 |
|---|---|
| Load Balancer | 在多台主機之間分配流量,可逐台切換 |
| Floating IP | Vultr 提供的虛擬 IP,可瞬間切換指向 |
| Managed Database(RDS) | 資料庫獨立於 VPS,遷移時不需要搬資料庫 |
| Galera Cluster | MariaDB 多主同步,任一節點都可讀寫 |
| Kubernetes | 容器編排,支援 rolling update |
這些方案的共同特點是架構複雜度與成本都顯著提升。對於單台 VPS + DNS 的架構來說,短暫維護模式已經是風險最低、成本最低的最佳解。
小結
這套遷移方案的核心思路是「提前同步、最後切換」:
- 利用 MariaDB Replication 在背景持續同步資料,使用者無感
- 最後短暫停止寫入,確保資料完全一致
- 切換 DNS,新主機正式接手
- 舊主機保留作為 rollback 備案
適用於任何持續有寫入流量的系統——SaaS、API 服務、電商、CMS、後台管理系統等。只要資料庫是 MariaDB/MySQL,這套方法都能直接套用。
