<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>模組六：高可用與災難復原 on Tarragon</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/</link><description>Recent content in 模組六：高可用與災難復原 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sat, 20 Jun 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/operations/06-high-availability/index.xml" rel="self" type="application/rss+xml"/><item><title>單點故障盤點</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/spof-inventory/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/operations/06-high-availability/spof-inventory/</guid><description>&lt;p>哪些元件一掛、整個系統就跟著掛？把這些點找出來，就是單點故障盤點。高可用的核心是冗餘——每個單點都有替代路徑——但在設計冗餘之前，得先知道單點在哪。盤點的方法是主動反推，而不是等出事後回頭找：假設某個變更已經在 production 造成了事故，倒著推它會怎麼壞、壞了會擴散到哪。這種 pre-mortem 的成本極低（一次結構化討論），卻能在事故發生前就把單點攤開。&lt;/p>
&lt;h2 id="pre-mortem假設已經出事反推路徑">Pre-mortem：假設已經出事，反推路徑&lt;/h2>
&lt;p>Pre-mortem 的核心假設是「這個變更已經在 production 造成事故」，從這個假設反向推導失敗路徑。它分四步走。先列出所有依賴與資料路徑——服務之間的依賴、資料的寫入路徑、對外部的呼叫、以及 schema、config、流量路由這些容易被忽略的隱性依賴。再對每一條路徑問「它斷了、慢了、或回錯了會怎樣」，追蹤影響怎麼擴散到直接依賴方、上游呼叫者、使用者可見的行為、以及資料一致性。接著判斷現有的驗證擋不擋得住這些失敗——CI、壓測、chaos、contract test 有沒有覆蓋，重點是找出「以為有覆蓋、實際上沒有」的那些。最後把識別出的缺口路由出去。&lt;/p>
&lt;p>第四步最容易失敗。缺口列了、但沒有 owner、沒有 deadline、沒有路由到下一步，pre-mortem 就淪為一份會議紀錄——問題盤點出來了卻沒人修，跟沒盤點差別不大。上線前補得了的缺口進就緒審查、失敗假設值得驗證的轉成 chaos 實驗、上線前補不了的進技術債追蹤。盤點的價值不在列出多少缺口，在每個缺口都有明確的去處。&lt;/p>
&lt;h2 id="依賴-budget自家可用性被依賴封頂">依賴 budget：自家可用性被依賴封頂&lt;/h2>
&lt;p>盤點單點時，一個容易被忽略的單點是外部依賴。自家服務的可用性是所有依賴可用性的乘積——一個 99.9% 的依賴，乘上自家的 99.9%，上限就只剩 99.8%。這意味著關鍵路徑上每多一個沒有替代路徑的依賴，就把自家可用性的天花板往下壓一層。盤點依賴風險不能只看它宣稱的 SLA，要看它失效之後自家還剩多少降級能力、以及失效的 blast radius 有多大。&lt;/p>
&lt;p>依賴盤點有三個關鍵訊號要查：關鍵路徑上有沒有「不知道掛了會怎樣」的依賴（這種是最危險的單點，因為連影響都沒摸清）、每個依賴有沒有明確的 failure domain（它的失效會被關在哪個範圍）、以及有沒有 graceful degradation 或 fallback（依賴掛了能不能降級服務而非整個停）。這三個訊號裡，控制面類的依賴風險通常最高——它一掛，可能連恢復動作本身都做不了。&lt;/p>
&lt;h2 id="失效模式分類與排序">失效模式分類與排序&lt;/h2>
&lt;p>盤點出來的缺口要分類、排序，不能一視同仁。按失效模式分成四類看得比較清楚：高風險變更缺差異化的驗證 gate、壓測模型沒覆蓋失敗流量（retry 風暴、timeout 級聯、佇列堆積）、rollback 或 DR 路徑事故前沒真的跑過（「有計畫但沒演練」，特徵是 schema 已經不向下相容、failover 的 config 已經漂移）、以及告警延遲或缺失讓使用者比監控先發現。&lt;/p>
&lt;p>排序用三個軸：嚴重度（失效的 blast radius 有多大——單服務、跨服務、跨區、還是跨租戶）、發生機率（這條失效路徑多常被觸及）、偵測難度（發現要多久）。三軸相乘，高嚴重度、高機率、又難偵測的缺口最先處理——難偵測特別致命，因為它讓一個高影響的故障可以悄悄壞很久。這裡的陷阱是把評分本身當成目標，維護一套精密評分的成本超過了它帶來的判讀價值，就本末倒置了。&lt;/p>
&lt;h2 id="失效局部化把單點的影響關進小範圍">失效局部化：把單點的影響關進小範圍&lt;/h2>
&lt;p>盤點的目標不只是找出單點，更是把單點失效的影響局部化——限制在最小的可影響範圍內。一個依賴退化，理想的結果不是「整個服務全停」，而是「只有一個 cell 受影響」。做到這點的機制包括把系統切成獨立的 cell（劃出擴散邊界）、用某種分片讓不同用戶的故障不重疊、讓控制面與資料面解耦（控制面掛了資料面還能服務）、以及讓失敗時的工作量保持恆定（避免故障觸發額外負載放大）。&lt;/p>
&lt;p>局部化改變了依賴 budget 的算法。當單一依賴的失效被關在一個 cell 裡，budget 算式裡「這個依賴失效」對應的就不是「整個服務全停」，而是「最大可影響一個 cell」——同樣的依賴、同樣的失效機率，影響面小了一個數量級。盤點單點時要問的不只是「它會不會掛」，還有「它掛了的影響能不能被關起來」。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>找出單點之後，怎麼用冗餘給它替代路徑 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a>&lt;/li>
&lt;li>單點掛了怎麼自動切到替代路徑 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制&lt;/a>&lt;/li>
&lt;li>rollback 與 DR 路徑「有計畫但沒演練」怎麼補 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略&lt;/a>&lt;/li>
&lt;li>依賴的可靠性預算與失效局部化的完整設計 → &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">backend 依賴可靠性預算&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>哪些元件一掛、整個系統就跟著掛？把這些點找出來，就是單點故障盤點。高可用的核心是冗餘——每個單點都有替代路徑——但在設計冗餘之前，得先知道單點在哪。盤點的方法是主動反推，而不是等出事後回頭找：假設某個變更已經在 production 造成了事故，倒著推它會怎麼壞、壞了會擴散到哪。這種 pre-mortem 的成本極低（一次結構化討論），卻能在事故發生前就把單點攤開。</p>
<h2 id="pre-mortem假設已經出事反推路徑">Pre-mortem：假設已經出事，反推路徑</h2>
<p>Pre-mortem 的核心假設是「這個變更已經在 production 造成事故」，從這個假設反向推導失敗路徑。它分四步走。先列出所有依賴與資料路徑——服務之間的依賴、資料的寫入路徑、對外部的呼叫、以及 schema、config、流量路由這些容易被忽略的隱性依賴。再對每一條路徑問「它斷了、慢了、或回錯了會怎樣」，追蹤影響怎麼擴散到直接依賴方、上游呼叫者、使用者可見的行為、以及資料一致性。接著判斷現有的驗證擋不擋得住這些失敗——CI、壓測、chaos、contract test 有沒有覆蓋，重點是找出「以為有覆蓋、實際上沒有」的那些。最後把識別出的缺口路由出去。</p>
<p>第四步最容易失敗。缺口列了、但沒有 owner、沒有 deadline、沒有路由到下一步，pre-mortem 就淪為一份會議紀錄——問題盤點出來了卻沒人修，跟沒盤點差別不大。上線前補得了的缺口進就緒審查、失敗假設值得驗證的轉成 chaos 實驗、上線前補不了的進技術債追蹤。盤點的價值不在列出多少缺口，在每個缺口都有明確的去處。</p>
<h2 id="依賴-budget自家可用性被依賴封頂">依賴 budget：自家可用性被依賴封頂</h2>
<p>盤點單點時，一個容易被忽略的單點是外部依賴。自家服務的可用性是所有依賴可用性的乘積——一個 99.9% 的依賴，乘上自家的 99.9%，上限就只剩 99.8%。這意味著關鍵路徑上每多一個沒有替代路徑的依賴，就把自家可用性的天花板往下壓一層。盤點依賴風險不能只看它宣稱的 SLA，要看它失效之後自家還剩多少降級能力、以及失效的 blast radius 有多大。</p>
<p>依賴盤點有三個關鍵訊號要查：關鍵路徑上有沒有「不知道掛了會怎樣」的依賴（這種是最危險的單點，因為連影響都沒摸清）、每個依賴有沒有明確的 failure domain（它的失效會被關在哪個範圍）、以及有沒有 graceful degradation 或 fallback（依賴掛了能不能降級服務而非整個停）。這三個訊號裡，控制面類的依賴風險通常最高——它一掛，可能連恢復動作本身都做不了。</p>
<h2 id="失效模式分類與排序">失效模式分類與排序</h2>
<p>盤點出來的缺口要分類、排序，不能一視同仁。按失效模式分成四類看得比較清楚：高風險變更缺差異化的驗證 gate、壓測模型沒覆蓋失敗流量（retry 風暴、timeout 級聯、佇列堆積）、rollback 或 DR 路徑事故前沒真的跑過（「有計畫但沒演練」，特徵是 schema 已經不向下相容、failover 的 config 已經漂移）、以及告警延遲或缺失讓使用者比監控先發現。</p>
<p>排序用三個軸：嚴重度（失效的 blast radius 有多大——單服務、跨服務、跨區、還是跨租戶）、發生機率（這條失效路徑多常被觸及）、偵測難度（發現要多久）。三軸相乘，高嚴重度、高機率、又難偵測的缺口最先處理——難偵測特別致命，因為它讓一個高影響的故障可以悄悄壞很久。這裡的陷阱是把評分本身當成目標，維護一套精密評分的成本超過了它帶來的判讀價值，就本末倒置了。</p>
<h2 id="失效局部化把單點的影響關進小範圍">失效局部化：把單點的影響關進小範圍</h2>
<p>盤點的目標不只是找出單點，更是把單點失效的影響局部化——限制在最小的可影響範圍內。一個依賴退化，理想的結果不是「整個服務全停」，而是「只有一個 cell 受影響」。做到這點的機制包括把系統切成獨立的 cell（劃出擴散邊界）、用某種分片讓不同用戶的故障不重疊、讓控制面與資料面解耦（控制面掛了資料面還能服務）、以及讓失敗時的工作量保持恆定（避免故障觸發額外負載放大）。</p>
<p>局部化改變了依賴 budget 的算法。當單一依賴的失效被關在一個 cell 裡，budget 算式裡「這個依賴失效」對應的就不是「整個服務全停」，而是「最大可影響一個 cell」——同樣的依賴、同樣的失效機率，影響面小了一個數量級。盤點單點時要問的不只是「它會不會掛」，還有「它掛了的影響能不能被關起來」。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>找出單點之後，怎麼用冗餘給它替代路徑 → <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a></li>
<li>單點掛了怎麼自動切到替代路徑 → <a href="/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制</a></li>
<li>rollback 與 DR 路徑「有計畫但沒演練」怎麼補 → <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略</a></li>
<li>依賴的可靠性預算與失效局部化的完整設計 → <a href="/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">backend 依賴可靠性預算</a></li>
</ul>
]]></content:encoded></item><item><title>冗餘設計模式</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/</guid><description>&lt;p>單點有了替代路徑之後，那一份備援要怎麼擺——閒著等、還是也一起服務？冗餘設計模式沿兩個維度區分：備援的那一份服不服務流量（active-passive 的備援閒著等、active-active 與機群式的備援也在幹活），以及資料怎麼同步（同步副本幾乎不丟資料、非同步副本有延遲窗口）。選哪一種，決定了冗餘的成本、切換的速度、以及切換時可能丟多少資料。&lt;/p>
&lt;h2 id="active-passive備援熱備不服務流量">Active-passive：備援熱備、不服務流量&lt;/h2>
&lt;p>Active-passive 是最基礎的冗餘形態：有一個備援節點存在、隨時準備接手，但平時不服務任何流量。雲端資料庫的 multi-AZ 就是它的典型形態——用一個布林屬性開啟，背後是在另一個可用區維護一個同步副本，主庫的可用區故障時自動切到這個 standby，秒級到一兩分鐘的窗口後恢復。這個 standby 是熱備、不可讀——它不接受任何查詢流量、也不提供讀取擴展，純粹在那裡等 failover。要分攤讀流量得另開唯讀副本（那是另一個資源、另一個機制）。&lt;/p>
&lt;p>Active-passive 的可用性不是零中斷。failover 期間，應用到資料庫的連線會斷、需要重連；應用層若沒有連線中斷後的重試邏輯，這個 failover 就從「透明切換」變成「使用者可見的服務中斷」。冗餘節點準備好了，不代表切換對上層是無感的——上層要配合處理切換瞬間的連線中斷，冗餘才真的透明。這個「切換對上層透明」的前提，是 failover 機制那章的主題。&lt;/p>
&lt;h2 id="active-active備援也服務流量">Active-active：備援也服務流量&lt;/h2>
&lt;p>Active-active 讓備援的那一份也承接流量，不是閒著等。它的好處是那份冗餘資源沒有閒置——平時就在分攤負載、故障時少一份也還撐得住。代價是它要求所有份都能同時服務，對有狀態的部分（資料庫）意味著多份要同時可寫或至少可讀，資料一致性的協調比 active-passive 複雜得多。無狀態的應用層做 active-active 很自然（每個實例都對等，這正是 &lt;a href="https://tarrragon.github.io/blog/operations/02-horizontal-scaling/" data-link-title="模組二：水平擴展" data-link-desc="一個實例不夠時怎麼加第二個 — stateless 設計、shared storage、session 處理的工程約束">水平擴展&lt;/a> 的無狀態設計）；有狀態的資料層做 active-active 要處理多寫衝突或讀寫分離，難度高得多。&lt;/p>
&lt;h2 id="n1nm無狀態機群的冗餘">N+1／N+M：無狀態機群的冗餘&lt;/h2>
&lt;p>無狀態機群的冗餘不是「一份主、一份備」的成對，而是「N 台在服務、多備 M 台」的機群。這是無狀態水平擴展的自然延伸——每台實例對等，冗餘就是多開幾台一樣的實例。N+1 表示在滿足負載所需的 N 台之外多備 1 台，能容忍同時掛 1 台不掉服務；要容忍同時掛 M 台就是 N+M。&lt;/p>
&lt;p>N+M 跟 active-passive 熱備對的差別在成本結構。熱備是 1:1、一份整份閒置，成本翻倍（2x）；N+M 的備援攤到整個機群，一個 10 台的機群多備 1 台只多約 10% 的開銷。所以無狀態層的高可用便宜得多——它不需要為每一份服務的實例都配一份閒置備援，只要機群整體多留幾台的餘裕。這條讓成本章的「冗餘至少 2x」有了下限：2x 是有狀態熱備的上界、N+1／N+M 是無狀態機群的下界，見 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本&lt;/a>。&lt;/p>
&lt;h2 id="multi-region在冗餘之上疊地理層">Multi-region：在冗餘之上疊地理層&lt;/h2>
&lt;p>Multi-region 是在 active-passive 或 active-active 之上再疊一層地理冗餘，解的是「整個 region 不可用」的極端情境。它靠幾個機制組合：跨 region 的唯讀副本、跨 region 的物件儲存複製、以及 DNS 層的 failover 路由（健康檢查加 DNS 切換）。做到極致的可用性很可觀——有客服平台跨 15 個 region 用分散式資料庫達成 99.999% 的可用性，等於一年只停機約 5 分鐘。&lt;/p>
&lt;p>Multi-region 跟同 region 冗餘的關鍵差異在資料同步。同 region 的 multi-AZ 是同步副本，failover 幾乎不丟資料；跨 region 的複製是非同步的、有延遲，failover 時會落在「複製延遲窗口」裡的資料就丟了。這個同步方式的差異直接決定了能承受多少資料遺失——同步副本對應接近零的資料落差，非同步跨 region 對應一個延遲窗口的落差。這條差異是 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">disaster recovery&lt;/a> 裡 RPO 的來源。&lt;/p>
&lt;h2 id="冗餘不等於備份">冗餘不等於備份&lt;/h2>
&lt;p>冗餘模式有一個常見的誤解要拆穿：冗餘防的是硬體與可用區故障，不防邏輯損壞。multi-AZ 的 standby 是同步副本——一個誤刪的 table、一個算錯的批次 UPDATE、一個有 bug 的 migration，會被同步複製到 standby，兩份一起壞。active-active 也一樣，錯誤的寫入會傳到每一份。冗餘讓「硬體掛了還有另一份」，但那另一份跟壞掉的這份內容一模一樣，對邏輯錯誤毫無保護。&lt;/p>
&lt;p>防邏輯損壞的是另一條正交的防線：備份與時間點還原（PITR）。冗餘管的是可用性（硬體或 AZ 掛了服務不中斷），備份管的是可還原性（資料被邏輯性破壞後能倒回某個時間點）。這兩者職責正交，要分別配置、分別驗證——不能把冗餘當成備份，也不能因為有備份就省掉冗餘。&lt;/p>
&lt;h2 id="冗餘要靠-drill-驗證">冗餘要靠 drill 驗證&lt;/h2>
&lt;p>冗餘設計「宣稱有效」不等於「實測有效」。一個 multi-AZ 切換窗口寫在文件上說「秒級」，跟它在真實故障下確實秒級切換，是兩回事——中間可能卡在應用沒重連、監控誤報、或 failover 腳本的某個前提在 production 不成立。驗證的手段是 chaos drill：用基礎設施層的故障注入（AZ failure、region failure，雲端的 chaos 工具支援）真的打掉一個可用區，看冗餘有沒有按預期接手、切換窗口是不是真的在承諾內。冗餘設計要從紙面轉成證據，靠的是演練，這條延伸到 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">disaster recovery&lt;/a> 的演練節奏。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>冗餘準備好了，切換怎麼觸發、怎麼對上層透明 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制&lt;/a>&lt;/li>
&lt;li>同步 vs 非同步副本怎麼對應 RPO、演練怎麼跑 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略&lt;/a>&lt;/li>
&lt;li>冗餘至少 2x 資源，值不值得 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本&lt;/a>&lt;/li>
&lt;li>multi-AZ 是 infra 層的能力，怎麼在 IaC 開啟 → &lt;a href="https://tarrragon.github.io/blog/infra/05-core-services/stateful-protection-dependency/" data-link-title="Stateful 資源保護與跨服務依賴表達" data-link-desc="stateful 資源的保護策略（multi-AZ、備份、刪除保護）、stateful 與 stateless 的操作差異，以及用 output 與 data source 表達服務間依賴">infra Stateful 資源保護&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>單點有了替代路徑之後，那一份備援要怎麼擺——閒著等、還是也一起服務？冗餘設計模式沿兩個維度區分：備援的那一份服不服務流量（active-passive 的備援閒著等、active-active 與機群式的備援也在幹活），以及資料怎麼同步（同步副本幾乎不丟資料、非同步副本有延遲窗口）。選哪一種，決定了冗餘的成本、切換的速度、以及切換時可能丟多少資料。</p>
<h2 id="active-passive備援熱備不服務流量">Active-passive：備援熱備、不服務流量</h2>
<p>Active-passive 是最基礎的冗餘形態：有一個備援節點存在、隨時準備接手，但平時不服務任何流量。雲端資料庫的 multi-AZ 就是它的典型形態——用一個布林屬性開啟，背後是在另一個可用區維護一個同步副本，主庫的可用區故障時自動切到這個 standby，秒級到一兩分鐘的窗口後恢復。這個 standby 是熱備、不可讀——它不接受任何查詢流量、也不提供讀取擴展，純粹在那裡等 failover。要分攤讀流量得另開唯讀副本（那是另一個資源、另一個機制）。</p>
<p>Active-passive 的可用性不是零中斷。failover 期間，應用到資料庫的連線會斷、需要重連；應用層若沒有連線中斷後的重試邏輯，這個 failover 就從「透明切換」變成「使用者可見的服務中斷」。冗餘節點準備好了，不代表切換對上層是無感的——上層要配合處理切換瞬間的連線中斷，冗餘才真的透明。這個「切換對上層透明」的前提，是 failover 機制那章的主題。</p>
<h2 id="active-active備援也服務流量">Active-active：備援也服務流量</h2>
<p>Active-active 讓備援的那一份也承接流量，不是閒著等。它的好處是那份冗餘資源沒有閒置——平時就在分攤負載、故障時少一份也還撐得住。代價是它要求所有份都能同時服務，對有狀態的部分（資料庫）意味著多份要同時可寫或至少可讀，資料一致性的協調比 active-passive 複雜得多。無狀態的應用層做 active-active 很自然（每個實例都對等，這正是 <a href="/blog/operations/02-horizontal-scaling/" data-link-title="模組二：水平擴展" data-link-desc="一個實例不夠時怎麼加第二個 — stateless 設計、shared storage、session 處理的工程約束">水平擴展</a> 的無狀態設計）；有狀態的資料層做 active-active 要處理多寫衝突或讀寫分離，難度高得多。</p>
<h2 id="n1nm無狀態機群的冗餘">N+1／N+M：無狀態機群的冗餘</h2>
<p>無狀態機群的冗餘不是「一份主、一份備」的成對，而是「N 台在服務、多備 M 台」的機群。這是無狀態水平擴展的自然延伸——每台實例對等，冗餘就是多開幾台一樣的實例。N+1 表示在滿足負載所需的 N 台之外多備 1 台，能容忍同時掛 1 台不掉服務；要容忍同時掛 M 台就是 N+M。</p>
<p>N+M 跟 active-passive 熱備對的差別在成本結構。熱備是 1:1、一份整份閒置，成本翻倍（2x）；N+M 的備援攤到整個機群，一個 10 台的機群多備 1 台只多約 10% 的開銷。所以無狀態層的高可用便宜得多——它不需要為每一份服務的實例都配一份閒置備援，只要機群整體多留幾台的餘裕。這條讓成本章的「冗餘至少 2x」有了下限：2x 是有狀態熱備的上界、N+1／N+M 是無狀態機群的下界，見 <a href="/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本</a>。</p>
<h2 id="multi-region在冗餘之上疊地理層">Multi-region：在冗餘之上疊地理層</h2>
<p>Multi-region 是在 active-passive 或 active-active 之上再疊一層地理冗餘，解的是「整個 region 不可用」的極端情境。它靠幾個機制組合：跨 region 的唯讀副本、跨 region 的物件儲存複製、以及 DNS 層的 failover 路由（健康檢查加 DNS 切換）。做到極致的可用性很可觀——有客服平台跨 15 個 region 用分散式資料庫達成 99.999% 的可用性，等於一年只停機約 5 分鐘。</p>
<p>Multi-region 跟同 region 冗餘的關鍵差異在資料同步。同 region 的 multi-AZ 是同步副本，failover 幾乎不丟資料；跨 region 的複製是非同步的、有延遲，failover 時會落在「複製延遲窗口」裡的資料就丟了。這個同步方式的差異直接決定了能承受多少資料遺失——同步副本對應接近零的資料落差，非同步跨 region 對應一個延遲窗口的落差。這條差異是 <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">disaster recovery</a> 裡 RPO 的來源。</p>
<h2 id="冗餘不等於備份">冗餘不等於備份</h2>
<p>冗餘模式有一個常見的誤解要拆穿：冗餘防的是硬體與可用區故障，不防邏輯損壞。multi-AZ 的 standby 是同步副本——一個誤刪的 table、一個算錯的批次 UPDATE、一個有 bug 的 migration，會被同步複製到 standby，兩份一起壞。active-active 也一樣，錯誤的寫入會傳到每一份。冗餘讓「硬體掛了還有另一份」，但那另一份跟壞掉的這份內容一模一樣，對邏輯錯誤毫無保護。</p>
<p>防邏輯損壞的是另一條正交的防線：備份與時間點還原（PITR）。冗餘管的是可用性（硬體或 AZ 掛了服務不中斷），備份管的是可還原性（資料被邏輯性破壞後能倒回某個時間點）。這兩者職責正交，要分別配置、分別驗證——不能把冗餘當成備份，也不能因為有備份就省掉冗餘。</p>
<h2 id="冗餘要靠-drill-驗證">冗餘要靠 drill 驗證</h2>
<p>冗餘設計「宣稱有效」不等於「實測有效」。一個 multi-AZ 切換窗口寫在文件上說「秒級」，跟它在真實故障下確實秒級切換，是兩回事——中間可能卡在應用沒重連、監控誤報、或 failover 腳本的某個前提在 production 不成立。驗證的手段是 chaos drill：用基礎設施層的故障注入（AZ failure、region failure，雲端的 chaos 工具支援）真的打掉一個可用區，看冗餘有沒有按預期接手、切換窗口是不是真的在承諾內。冗餘設計要從紙面轉成證據，靠的是演練，這條延伸到 <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">disaster recovery</a> 的演練節奏。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>冗餘準備好了，切換怎麼觸發、怎麼對上層透明 → <a href="/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制</a></li>
<li>同步 vs 非同步副本怎麼對應 RPO、演練怎麼跑 → <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略</a></li>
<li>冗餘至少 2x 資源，值不值得 → <a href="/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本</a></li>
<li>multi-AZ 是 infra 層的能力，怎麼在 IaC 開啟 → <a href="/blog/infra/05-core-services/stateful-protection-dependency/" data-link-title="Stateful 資源保護與跨服務依賴表達" data-link-desc="stateful 資源的保護策略（multi-AZ、備份、刪除保護）、stateful 與 stateless 的操作差異，以及用 output 與 data source 表達服務間依賴">infra Stateful 資源保護</a></li>
</ul>
]]></content:encoded></item><item><title>Failover 機制</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/</guid><description>&lt;p>單點掛了，怎麼自動切到替代路徑？failover 機制把這件事拆成三個環節：怎麼知道要切（觸發）、切到哪與怎麼切（切換）、以及事後怎麼把系統收回穩態（恢復順序）。三者裡最危險的往往是恢復順序、而不是切換本身——切換做對了、恢復動作卻因為依賴一個還沒恢復的元件而卡死，把一次可控的故障拖成漫長的中斷。&lt;/p>
&lt;h2 id="觸發探活是-failover-的前提">觸發：探活是 failover 的前提&lt;/h2>
&lt;p>Failover 的觸發條件是探活——健康檢查判定某個節點不健康，才觸發切換。這是 &lt;a href="https://tarrragon.github.io/blog/operations/04-service-health/" data-link-title="模組四：服務探活與自動恢復" data-link-desc="服務掛了怎麼自動發現和恢復 — health check 設計、liveness vs readiness、systemd watchdog、process supervisor">模組四 服務探活&lt;/a> 的主題：沒有可靠的探活，failover 要嘛切得太晚（壞了很久才發現）、要嘛切得太急（一次抖動就誤判、觸發不必要的 failover）。自動 failover 快、但依賴探活的準確度，探活抖動會讓它反覆切換；手動 failover 慢、但多了一層人的判斷，適合切換代價高、誤切損失大的場景。選自動還是手動，取決於「切錯的代價」跟「切慢的代價」哪個大。&lt;/p>
&lt;h2 id="切換先劃定故障域否則恢復動作變放大器">切換：先劃定故障域，否則恢復動作變放大器&lt;/h2>
&lt;p>切換之前要先知道這次故障的邊界到哪——它最多會影響到哪個範圍。這個故障域（fault domain）如果沒有預先定義，恢復動作本身可能變成新的放大器：以為只是切一個節點、實際上牽動了跨區的共享路徑，切換的動作反而把故障擴散得更廣。跨區的高可用尤其要先劃清楚「這個故障最多蔓延到哪裡」，才知道 failover 要切多大範圍、以及切換不會誤傷到本來健康的部分。&lt;/p>
&lt;p>切換要盯三個訊號判斷它有沒有失控：跨區的錯誤是不是在越界擴散、failover 的完成進度有沒有在收斂、以及共享的依賴有沒有變成瓶頸。這三個訊號來自大型平台跨區故障的實戰——它們揭露一件事：大規模系統真正的擴散面在跨區共享的相依路徑、不在單點失效本身，單點失效只是觸發點。&lt;/p>
&lt;h2 id="恢復順序循環等待是最大的風險">恢復順序：循環等待是最大的風險&lt;/h2>
&lt;p>恢復順序決定整體恢復時間，而它最大的風險是循環等待。系統大致分兩層：控制面是管理與調度那一層（下發設定、決定路由、協調誰接手），資料面是實際處理請求流量那一層。當控制面與資料面共用某條路徑、而恢復動作又依賴一個尚未恢復的控制面服務時，恢復就卡在一個環裡——要恢復 A 得先有 B、要恢復 B 得先有 A。有大型平台在一次全區故障裡就撞到這個：恢復需要的工具本身依賴了已經故障的系統（網路路由、DNS、遠端存取），結果連「開始恢復」這個動作都做不了，故障時間被恢復工具的循環依賴大幅拉長。&lt;/p>
&lt;p>所以恢復要分批、不能同時恢復所有路徑。同時把多條路徑一起拉起來，可能在剛恢復、還很脆弱的依賴上引發回源放大（原本被快取或前端擋掉的請求，因為那層還沒回來、全部同時回打源頭）或連鎖過載，把一次可控的恢復變成第二次故障。可靠的做法是依事故的時間線與既定的 runbook 安排恢復批次，每一批先驗證 baseline 穩定了、再進下一批。恢復順序的設計原則因此有兩條：讓恢復路徑不依賴任何可能故障的控制面（恢復工具要能在控制面掛掉時獨立運作）、以及分批推進而非一次全開。&lt;/p>
&lt;h2 id="資料一致性rollback-還是-roll-forward">資料一致性：rollback 還是 roll-forward&lt;/h2>
&lt;p>Failover 或變更失敗時，除了切走流量，還有一個資料層的決策：退回舊版（rollback）還是往前修（roll-forward）。判斷取決於這個變更可不可逆、以及新資料是否已經依賴了新結構。可逆的（schema 向下相容、feature flag 可關、路由可切回）用 rollback，它通常比 roll-forward 快收斂，因為退回的是一個已經被驗證過的行為；不可逆的（新版已經寫入了不能回退的資料）只能 roll-forward。還有一種混合：先 rollback 止血、穩定後再 roll-forward 修復。&lt;/p>
&lt;p>這個判斷有一個容易漏的層次：rollback 的安全性不只看部署層、還要看資料語義層。一個交易系統的 rollback，要同時處理 schema 相容跟冪等重播——退回程式版本容易，但那段期間寫入的資料若跟新版本的語義綁定，光退版會留下不一致。判斷 rollback 還是 roll-forward，五個軸要一起看：schema 相容性、資料狀態、修復時間、feature flag、下游依賴。&lt;/p>
&lt;h2 id="依賴隔離切斷共享相依的放大">依賴隔離：切斷共享相依的放大&lt;/h2>
&lt;p>Failover 能不能乾淨切換，很大程度取決於依賴有沒有被隔離。共享的相依路徑是故障放大的主要通道——一個依賴退化，透過共享路徑拖垮所有用到它的服務。隔離的做法是把不同的工作負載、不同的租戶關進各自的資源池，一個池的故障不外溢到別的池，這正是 &lt;a href="https://tarrragon.github.io/blog/operations/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控&lt;/a> 的 bulkhead 隔離搬到高可用場景。依賴隔離做得好，failover 只需要切掉受影響的那個隔離區，不必動到整個系統。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>Failover 的觸發前提——探活怎麼做 → &lt;a href="https://tarrragon.github.io/blog/operations/04-service-health/" data-link-title="模組四：服務探活與自動恢復" data-link-desc="服務掛了怎麼自動發現和恢復 — health check 設計、liveness vs readiness、systemd watchdog、process supervisor">模組四 服務探活&lt;/a>&lt;/li>
&lt;li>冗餘準備好才有得切、切換對上層透明的前提 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a>&lt;/li>
&lt;li>恢復順序、restore 驗證與演練節奏 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略&lt;/a>&lt;/li>
&lt;li>Bulkhead 隔離怎麼切斷共享相依 → &lt;a href="https://tarrragon.github.io/blog/operations/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>單點掛了，怎麼自動切到替代路徑？failover 機制把這件事拆成三個環節：怎麼知道要切（觸發）、切到哪與怎麼切（切換）、以及事後怎麼把系統收回穩態（恢復順序）。三者裡最危險的往往是恢復順序、而不是切換本身——切換做對了、恢復動作卻因為依賴一個還沒恢復的元件而卡死，把一次可控的故障拖成漫長的中斷。</p>
<h2 id="觸發探活是-failover-的前提">觸發：探活是 failover 的前提</h2>
<p>Failover 的觸發條件是探活——健康檢查判定某個節點不健康，才觸發切換。這是 <a href="/blog/operations/04-service-health/" data-link-title="模組四：服務探活與自動恢復" data-link-desc="服務掛了怎麼自動發現和恢復 — health check 設計、liveness vs readiness、systemd watchdog、process supervisor">模組四 服務探活</a> 的主題：沒有可靠的探活，failover 要嘛切得太晚（壞了很久才發現）、要嘛切得太急（一次抖動就誤判、觸發不必要的 failover）。自動 failover 快、但依賴探活的準確度，探活抖動會讓它反覆切換；手動 failover 慢、但多了一層人的判斷，適合切換代價高、誤切損失大的場景。選自動還是手動，取決於「切錯的代價」跟「切慢的代價」哪個大。</p>
<h2 id="切換先劃定故障域否則恢復動作變放大器">切換：先劃定故障域，否則恢復動作變放大器</h2>
<p>切換之前要先知道這次故障的邊界到哪——它最多會影響到哪個範圍。這個故障域（fault domain）如果沒有預先定義，恢復動作本身可能變成新的放大器：以為只是切一個節點、實際上牽動了跨區的共享路徑，切換的動作反而把故障擴散得更廣。跨區的高可用尤其要先劃清楚「這個故障最多蔓延到哪裡」，才知道 failover 要切多大範圍、以及切換不會誤傷到本來健康的部分。</p>
<p>切換要盯三個訊號判斷它有沒有失控：跨區的錯誤是不是在越界擴散、failover 的完成進度有沒有在收斂、以及共享的依賴有沒有變成瓶頸。這三個訊號來自大型平台跨區故障的實戰——它們揭露一件事：大規模系統真正的擴散面在跨區共享的相依路徑、不在單點失效本身，單點失效只是觸發點。</p>
<h2 id="恢復順序循環等待是最大的風險">恢復順序：循環等待是最大的風險</h2>
<p>恢復順序決定整體恢復時間，而它最大的風險是循環等待。系統大致分兩層：控制面是管理與調度那一層（下發設定、決定路由、協調誰接手），資料面是實際處理請求流量那一層。當控制面與資料面共用某條路徑、而恢復動作又依賴一個尚未恢復的控制面服務時，恢復就卡在一個環裡——要恢復 A 得先有 B、要恢復 B 得先有 A。有大型平台在一次全區故障裡就撞到這個：恢復需要的工具本身依賴了已經故障的系統（網路路由、DNS、遠端存取），結果連「開始恢復」這個動作都做不了，故障時間被恢復工具的循環依賴大幅拉長。</p>
<p>所以恢復要分批、不能同時恢復所有路徑。同時把多條路徑一起拉起來，可能在剛恢復、還很脆弱的依賴上引發回源放大（原本被快取或前端擋掉的請求，因為那層還沒回來、全部同時回打源頭）或連鎖過載，把一次可控的恢復變成第二次故障。可靠的做法是依事故的時間線與既定的 runbook 安排恢復批次，每一批先驗證 baseline 穩定了、再進下一批。恢復順序的設計原則因此有兩條：讓恢復路徑不依賴任何可能故障的控制面（恢復工具要能在控制面掛掉時獨立運作）、以及分批推進而非一次全開。</p>
<h2 id="資料一致性rollback-還是-roll-forward">資料一致性：rollback 還是 roll-forward</h2>
<p>Failover 或變更失敗時，除了切走流量，還有一個資料層的決策：退回舊版（rollback）還是往前修（roll-forward）。判斷取決於這個變更可不可逆、以及新資料是否已經依賴了新結構。可逆的（schema 向下相容、feature flag 可關、路由可切回）用 rollback，它通常比 roll-forward 快收斂，因為退回的是一個已經被驗證過的行為；不可逆的（新版已經寫入了不能回退的資料）只能 roll-forward。還有一種混合：先 rollback 止血、穩定後再 roll-forward 修復。</p>
<p>這個判斷有一個容易漏的層次：rollback 的安全性不只看部署層、還要看資料語義層。一個交易系統的 rollback，要同時處理 schema 相容跟冪等重播——退回程式版本容易，但那段期間寫入的資料若跟新版本的語義綁定，光退版會留下不一致。判斷 rollback 還是 roll-forward，五個軸要一起看：schema 相容性、資料狀態、修復時間、feature flag、下游依賴。</p>
<h2 id="依賴隔離切斷共享相依的放大">依賴隔離：切斷共享相依的放大</h2>
<p>Failover 能不能乾淨切換，很大程度取決於依賴有沒有被隔離。共享的相依路徑是故障放大的主要通道——一個依賴退化，透過共享路徑拖垮所有用到它的服務。隔離的做法是把不同的工作負載、不同的租戶關進各自的資源池，一個池的故障不外溢到別的池，這正是 <a href="/blog/operations/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控</a> 的 bulkhead 隔離搬到高可用場景。依賴隔離做得好，failover 只需要切掉受影響的那個隔離區，不必動到整個系統。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Failover 的觸發前提——探活怎麼做 → <a href="/blog/operations/04-service-health/" data-link-title="模組四：服務探活與自動恢復" data-link-desc="服務掛了怎麼自動發現和恢復 — health check 設計、liveness vs readiness、systemd watchdog、process supervisor">模組四 服務探活</a></li>
<li>冗餘準備好才有得切、切換對上層透明的前提 → <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a></li>
<li>恢復順序、restore 驗證與演練節奏 → <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略</a></li>
<li>Bulkhead 隔離怎麼切斷共享相依 → <a href="/blog/operations/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控</a></li>
</ul>
]]></content:encoded></item><item><title>Disaster recovery 策略</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/</guid><description>&lt;p>Disaster recovery 回答「災難發生後，服務能不能回來」。它有一條先於一切的原則：先確認路徑，再談速度。一份 backup 在被 restore 驗證過之前，它只是備份、不是復原能力；一套 failover 的 config 在沒跟 production 對齊之前，它只是文件、不是可執行的操作路由。RTO 跟 RPO 這些速度指標，是在「路徑確實走得通」之後才有意義的——路徑不通，再漂亮的目標數字都是空的。&lt;/p>
&lt;h2 id="rto-與-rpo是承諾不能是猜測">RTO 與 RPO：是承諾，不能是猜測&lt;/h2>
&lt;p>RTO（恢復時間目標）是「多久之內要恢復服務」，RPO（資料遺失目標）是「最多能丟多少資料」。這兩個數字有一個常見的陷阱：它們常常是估值、不是量值。一個寫在文件上「4 小時 RTO」的承諾，如果從沒真的跑過一次完整恢復，那 4 小時只是猜的——實際上 restore 本身可能就要 6 小時，這個承諾是空的。&lt;/p>
&lt;p>量 RTO 要量完整的時間，不只是資料還原那一段。真實的 RTO 從「決定啟動恢復」算起，涵蓋判斷、決策、執行、驗證，一路到服務真的恢復——中間任何一段的時間都算數。RPO 則由冗餘的資料同步方式決定：同步副本的 RPO 接近零，非同步跨 region 副本的 RPO 是那個複製延遲的窗口，這條在 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a> 講過。要讓這兩個數字從猜測變成承諾，只有一條路：用 restore drill 實際量測，拿量到的真實值去更新承諾。&lt;/p>
&lt;h2 id="rto-由備援的就緒程度決定">RTO 由備援的就緒程度決定&lt;/h2>
&lt;p>要達到某個 RTO，付出的成本取決於備援平時準備到多「熱」，這條光譜有公認的命名。最冷的是純備份還原（backup-restore）——平時只有備份、故障時從零重建環境，最便宜、但 RTO 最長。往上是 pilot-light——核心元件（如資料庫的副本）常態開著、其餘按需啟動，故障時把周邊點亮，中等成本與 RTO。再往上是 warm-standby——一個縮小規格的完整環境常態運轉、故障時放大到全量，RTO 更短。最熱的是 hot-standby（即 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a> 的 active-passive 熱備）——全規格備援常開、秒級到分鐘級切換，RTO 最短、成本最高。RTO 承諾要往哪一級靠，跟停機的商業代價一起算，見 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本&lt;/a>。&lt;/p>
&lt;h2 id="restore-驗證的三個層次">Restore 驗證的三個層次&lt;/h2>
&lt;p>備份的價值只在還原的那一刻才被證明。一個從沒被 restore 過的 backup，等於一個沒被驗證過的假設。restore 驗證要覆蓋三個層次。第一層是資料完整性——用 row count 比對、checksum、對帳查詢確認資料真的完整，這裡的失敗模式是 backup 的時段跨越了某個批次 job、或增量備份的鏈條中間斷了。第二層是服務可用性——config、secret、schema 版本、連線池這些元件 restore 之後可能失效，要跑 smoke test 加健康檢查確認服務真的起得來，不是只有資料回來了。第三層是恢復時間量測——這次 restore 實際花多久，拿去校準 RTO 承諾。&lt;/p>
&lt;p>這三層裡最容易被跳過的是「真的跑一次」。backup 有排程、每天都在備，但 restore 從來沒跑過——而 restore 是唯一能證明備份可用的手段。備份排程做得再勤，沒驗證過還原，就是在累積一堆不知道能不能用的檔案。&lt;/p>
&lt;h2 id="恢復不是切回流量就結束">恢復不是切回流量就結束&lt;/h2>
&lt;p>一個危險的誤解是把「切回流量」當成恢復完成。真實的恢復往往在切回流量之後還有很長一段。有遊戲平台的一次故障中斷了 73 小時，拉長的原因不在切換本身——是資料一致性要重建、快取要預熱、依賴服務要按正確順序啟動，這些在流量切回來之後才開始、而且各自要花時間。恢復的實際成本包含這些「切回之後」的收尾，把它們算漏，RTO 就會嚴重低估。&lt;/p>
&lt;p>恢復還要分批、不能一次全開——這條分批推進、恢復工具不依賴故障控制面的紀律，跟 &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制&lt;/a> 的恢復順序是同一套，在那裡展開。DR 這裡要補的是它跟 RTO 的關係：分批恢復本身要花時間、每批之間的驗證也要花時間，這些全部算進 RTO——把「切回之後」的收尾與分批的時間算漏，RTO 就會嚴重低估。&lt;/p>
&lt;h2 id="演練節奏計畫不演練就會漂移">演練節奏：計畫不演練就會漂移&lt;/h2>
&lt;p>DR 的能力會隨系統演進而悄悄失效——一份寫在 wiki、過去 12 個月沒演練過的 DR plan，基本上不可信，因為這 12 個月裡 production 一直在變、plan 早就跟現實漂移了。維持 DR 能力靠固定節奏的演練，不同類型有不同頻率：桌面推演（走一遍決策路由與角色分工）每季、局部 failover（切一個子系統、驗自動化腳本在 production 真的可執行）每半年、全區 failover（整區從災難回來、輸出 RTO/RPO 與資料一致性檢查）每年、資料還原演練每季。演練暴露的缺口要回寫進技術債追蹤——高優先的下個發布週期前修、次要的排入固定追蹤，不能演練完就散會。&lt;/p>
&lt;h2 id="dr-與-chaos-的分工">DR 與 chaos 的分工&lt;/h2>
&lt;p>DR 演練跟 chaos testing 容易混淆，但驗的是不同的事。chaos 驗「故障持續期間，服務能不能維持」——成功條件是穩態不被破壞、實驗結束系統還在運作；DR 驗「災難發生後，能不能回來」——成功條件是恢復路徑可執行、且符合 RTO/RPO，要經歷一次完整的失效加恢復循環。兩者的交集是 failover drill：chaos 關心切換期間退化多少，DR 關心切換完成後恢復的品質。要驗證高可用，兩者都需要——一個保證撐得住，一個保證回得來。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>RPO 的來源——同步 vs 非同步副本 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a>&lt;/li>
&lt;li>恢復順序的循環等待與分批恢復 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制&lt;/a>&lt;/li>
&lt;li>這一切要付多少、值不值得 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本&lt;/a>&lt;/li>
&lt;li>DR 與 rollback 演練的完整方法 → &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">backend DR 與 rollback 演練&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Disaster recovery 回答「災難發生後，服務能不能回來」。它有一條先於一切的原則：先確認路徑，再談速度。一份 backup 在被 restore 驗證過之前，它只是備份、不是復原能力；一套 failover 的 config 在沒跟 production 對齊之前，它只是文件、不是可執行的操作路由。RTO 跟 RPO 這些速度指標，是在「路徑確實走得通」之後才有意義的——路徑不通，再漂亮的目標數字都是空的。</p>
<h2 id="rto-與-rpo是承諾不能是猜測">RTO 與 RPO：是承諾，不能是猜測</h2>
<p>RTO（恢復時間目標）是「多久之內要恢復服務」，RPO（資料遺失目標）是「最多能丟多少資料」。這兩個數字有一個常見的陷阱：它們常常是估值、不是量值。一個寫在文件上「4 小時 RTO」的承諾，如果從沒真的跑過一次完整恢復，那 4 小時只是猜的——實際上 restore 本身可能就要 6 小時，這個承諾是空的。</p>
<p>量 RTO 要量完整的時間，不只是資料還原那一段。真實的 RTO 從「決定啟動恢復」算起，涵蓋判斷、決策、執行、驗證，一路到服務真的恢復——中間任何一段的時間都算數。RPO 則由冗餘的資料同步方式決定：同步副本的 RPO 接近零，非同步跨 region 副本的 RPO 是那個複製延遲的窗口，這條在 <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a> 講過。要讓這兩個數字從猜測變成承諾，只有一條路：用 restore drill 實際量測，拿量到的真實值去更新承諾。</p>
<h2 id="rto-由備援的就緒程度決定">RTO 由備援的就緒程度決定</h2>
<p>要達到某個 RTO，付出的成本取決於備援平時準備到多「熱」，這條光譜有公認的命名。最冷的是純備份還原（backup-restore）——平時只有備份、故障時從零重建環境，最便宜、但 RTO 最長。往上是 pilot-light——核心元件（如資料庫的副本）常態開著、其餘按需啟動，故障時把周邊點亮，中等成本與 RTO。再往上是 warm-standby——一個縮小規格的完整環境常態運轉、故障時放大到全量，RTO 更短。最熱的是 hot-standby（即 <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a> 的 active-passive 熱備）——全規格備援常開、秒級到分鐘級切換，RTO 最短、成本最高。RTO 承諾要往哪一級靠，跟停機的商業代價一起算，見 <a href="/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本</a>。</p>
<h2 id="restore-驗證的三個層次">Restore 驗證的三個層次</h2>
<p>備份的價值只在還原的那一刻才被證明。一個從沒被 restore 過的 backup，等於一個沒被驗證過的假設。restore 驗證要覆蓋三個層次。第一層是資料完整性——用 row count 比對、checksum、對帳查詢確認資料真的完整，這裡的失敗模式是 backup 的時段跨越了某個批次 job、或增量備份的鏈條中間斷了。第二層是服務可用性——config、secret、schema 版本、連線池這些元件 restore 之後可能失效，要跑 smoke test 加健康檢查確認服務真的起得來，不是只有資料回來了。第三層是恢復時間量測——這次 restore 實際花多久，拿去校準 RTO 承諾。</p>
<p>這三層裡最容易被跳過的是「真的跑一次」。backup 有排程、每天都在備，但 restore 從來沒跑過——而 restore 是唯一能證明備份可用的手段。備份排程做得再勤，沒驗證過還原，就是在累積一堆不知道能不能用的檔案。</p>
<h2 id="恢復不是切回流量就結束">恢復不是切回流量就結束</h2>
<p>一個危險的誤解是把「切回流量」當成恢復完成。真實的恢復往往在切回流量之後還有很長一段。有遊戲平台的一次故障中斷了 73 小時，拉長的原因不在切換本身——是資料一致性要重建、快取要預熱、依賴服務要按正確順序啟動，這些在流量切回來之後才開始、而且各自要花時間。恢復的實際成本包含這些「切回之後」的收尾，把它們算漏，RTO 就會嚴重低估。</p>
<p>恢復還要分批、不能一次全開——這條分批推進、恢復工具不依賴故障控制面的紀律，跟 <a href="/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制</a> 的恢復順序是同一套，在那裡展開。DR 這裡要補的是它跟 RTO 的關係：分批恢復本身要花時間、每批之間的驗證也要花時間，這些全部算進 RTO——把「切回之後」的收尾與分批的時間算漏，RTO 就會嚴重低估。</p>
<h2 id="演練節奏計畫不演練就會漂移">演練節奏：計畫不演練就會漂移</h2>
<p>DR 的能力會隨系統演進而悄悄失效——一份寫在 wiki、過去 12 個月沒演練過的 DR plan，基本上不可信，因為這 12 個月裡 production 一直在變、plan 早就跟現實漂移了。維持 DR 能力靠固定節奏的演練，不同類型有不同頻率：桌面推演（走一遍決策路由與角色分工）每季、局部 failover（切一個子系統、驗自動化腳本在 production 真的可執行）每半年、全區 failover（整區從災難回來、輸出 RTO/RPO 與資料一致性檢查）每年、資料還原演練每季。演練暴露的缺口要回寫進技術債追蹤——高優先的下個發布週期前修、次要的排入固定追蹤，不能演練完就散會。</p>
<h2 id="dr-與-chaos-的分工">DR 與 chaos 的分工</h2>
<p>DR 演練跟 chaos testing 容易混淆，但驗的是不同的事。chaos 驗「故障持續期間，服務能不能維持」——成功條件是穩態不被破壞、實驗結束系統還在運作；DR 驗「災難發生後，能不能回來」——成功條件是恢復路徑可執行、且符合 RTO/RPO，要經歷一次完整的失效加恢復循環。兩者的交集是 failover drill：chaos 關心切換期間退化多少，DR 關心切換完成後恢復的品質。要驗證高可用，兩者都需要——一個保證撐得住，一個保證回得來。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>RPO 的來源——同步 vs 非同步副本 → <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a></li>
<li>恢復順序的循環等待與分批恢復 → <a href="/blog/operations/06-high-availability/failover-mechanism/" data-link-title="Failover 機制" data-link-desc="設計單點掛掉自動切到替代路徑的機制時，釐清觸發靠探活、故障域要先劃定、恢復順序的循環等待風險、以及 rollback 與 roll-forward 怎麼選">Failover 機制</a></li>
<li>這一切要付多少、值不值得 → <a href="/blog/operations/06-high-availability/ha-cost/" data-link-title="高可用的成本" data-link-desc="判斷高可用值不值得時，用停機的商業代價衡量冗餘的 2x 成本、按可用性等級階梯評估投資、以及知道沒驗證的冗餘等於白付">高可用的成本</a></li>
<li>DR 與 rollback 演練的完整方法 → <a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">backend DR 與 rollback 演練</a></li>
</ul>
]]></content:encoded></item><item><title>高可用的成本</title><link>https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/operations/06-high-availability/ha-cost/</guid><description>&lt;p>高可用的成本核心是冗餘要多付一份資源，但多付多少取決於冗餘的形態，範圍從約 10% 到 100% 不等。最貴的一端是有狀態的熱備——一份 standby 跟主份同規格計費、平時完全閒置，等於把成本翻倍（2x）。最便宜的一端是無狀態機群的 N+1／N+M——一個 10 台的機群多加 1 台備援，只多約 10% 的開銷。所以「冗餘至少 2x」只對熱備成立，不能套到整套系統。這筆錢值不值得，不能用絕對數字判斷，要用「停機每小時的商業代價」衡量：一個停機一小時就損失巨大營收的服務，付冗餘換分鐘級 failover 很划算；一個停機幾小時無傷大雅的內部工具，付這筆冗餘就是浪費。高可用不是越高越好，是把可用性投資對齊停機的真實代價。&lt;/p>
&lt;h2 id="2x-的來源閒置的備援">2x 的來源：閒置的備援&lt;/h2>
&lt;p>冗餘的 2x 成本最直接的例子是資料庫的 multi-AZ——它的費用約是單一可用區的兩倍，因為那個 standby instance 按相同規格計費，卻不服務任何流量。這就是 active-passive 的閒置成本：備援存在、隨時準備接手，但平時純粹在燒錢等 failover。active-active 的冗餘資源閒置成本較低——那些資源平時就在分攤負載、沒閒著——但代價換到了資料一致性的協調成本上。更便宜的是無狀態機群的 N+1／N+M：機群本來就多台在分攤流量，多備一兩台的開銷攤到整個機群、比例很小（&lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a> 有這個形態的說明）。所以 2x 不是一個固定數字，是「這份冗餘是整份閒置的熱備、還是機群裡多備的幾台」決定的：閒置的熱備付全額閒置成本，機群式的備援只攤到小比例開銷。&lt;/p>
&lt;h2 id="用停機代價衡量值不值得">用停機代價衡量值不值得&lt;/h2>
&lt;p>判斷冗餘值不值得，用的是過度配置的經濟學——過度配置的成本好算、配置不足的代價難算，兩者的平衡點就是該投多少，完整的算法在 &lt;a href="https://tarrragon.github.io/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型&lt;/a> 展開過。套到高可用上，這個平衡點由停機代價定：關鍵服務的停機代價極高——電商每分鐘宕機對應可估算的營收損失——所以值得付 2x 甚至更多；非關鍵服務停機代價低，貼近最低配置跑就好。同一套判準，關鍵服務算出來要厚冗餘、非關鍵算出來可以薄，差別在停機的代價不同。&lt;/p>
&lt;h2 id="可用性等級是一道成本階梯">可用性等級是一道成本階梯&lt;/h2>
&lt;p>可用性不是連續的旋鈕，是一道階梯——每往上一級，成本與複雜度同步階梯上升。單一可用區是一級、跨可用區（multi-AZ）是一級、跨區域（multi-region）又是一級。多數服務的合理路徑是先把單一區域的 multi-AZ 加備份做扎實，再評估要不要跨區域，依據是業務對「整個區域級故障」的容忍度。&lt;/p>
&lt;p>跨區域這一級的決策特別要注意：它通常是合約 SLA 驅動的、不是技術判斷驅動的。一個 B2B SaaS 在合約裡承諾了某個可用性等級，跨區域投資才容易成立；純技術上「想更穩」很少足以正當化跨區域的成本與複雜度。可用性的頂級是有代價的錨——有平台跨 15 個區域做到 99.999%（一年停機約 5 分鐘），那個數字背後是十幾個區域各自維護的基礎設施。要不要爬到那一級，看的是合約與業務、不是工程的完美主義。&lt;/p>
&lt;h2 id="冗餘成本要有護欄">冗餘成本要有護欄&lt;/h2>
&lt;p>為可用性花錢也會失控，要有護欄。最典型的護欄是自動擴縮的成本上限——它是財務上的斷路器（&lt;a href="https://tarrragon.github.io/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型&lt;/a> 講過），設無限大就等著一次異常把帳單炸掉。高可用的投入同理：冗餘、備援、跨區複製每一項都要有成本上限，否則「為了更穩」會變成一個無底洞。可用性投資要跟一個明確的成本天花板綁在一起，超過就回頭重新評估這一級到底值不值得。&lt;/p>
&lt;h2 id="沒驗證的冗餘等於白付">沒驗證的冗餘等於白付&lt;/h2>
&lt;p>最後一筆容易漏算的成本是驗證。冗餘、DR、failover 都要靠演練驗證才算數，而演練要投入工程時間——這是高可用成本的一部分，不是額外選項。一個沒被 drill 驗證過的 multi-AZ、一份沒被 restore 過的 backup，是紙面上的冗餘：帳單上付了 2x，但真出事時它不一定接得住，等於白付了那筆冗餘成本。算高可用的總成本，要把「持續驗證的工程投入」算進去——冗餘的錢加上驗證的工，才是它真正的價格。省掉驗證的那份冗餘，是最貴的一種，因為它讓人以為有保障、實際沒有。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>過度配置的經濟學、autoscaler 的成本斷路器 → &lt;a href="https://tarrragon.github.io/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型&lt;/a>&lt;/li>
&lt;li>冗餘怎麼擺、2x 從哪來 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式&lt;/a>&lt;/li>
&lt;li>驗證冗餘的演練節奏 → &lt;a href="https://tarrragon.github.io/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略&lt;/a>&lt;/li>
&lt;li>完整的雲端成本治理 → &lt;a href="https://tarrragon.github.io/blog/operations/08-cost-management/" data-link-title="模組八：成本管理" data-link-desc="雲端帳單怎麼不失控 — reserved instance、spot instance、right-sizing、成本監控告警">模組八 成本管理&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>高可用的成本核心是冗餘要多付一份資源，但多付多少取決於冗餘的形態，範圍從約 10% 到 100% 不等。最貴的一端是有狀態的熱備——一份 standby 跟主份同規格計費、平時完全閒置，等於把成本翻倍（2x）。最便宜的一端是無狀態機群的 N+1／N+M——一個 10 台的機群多加 1 台備援，只多約 10% 的開銷。所以「冗餘至少 2x」只對熱備成立，不能套到整套系統。這筆錢值不值得，不能用絕對數字判斷，要用「停機每小時的商業代價」衡量：一個停機一小時就損失巨大營收的服務，付冗餘換分鐘級 failover 很划算；一個停機幾小時無傷大雅的內部工具，付這筆冗餘就是浪費。高可用不是越高越好，是把可用性投資對齊停機的真實代價。</p>
<h2 id="2x-的來源閒置的備援">2x 的來源：閒置的備援</h2>
<p>冗餘的 2x 成本最直接的例子是資料庫的 multi-AZ——它的費用約是單一可用區的兩倍，因為那個 standby instance 按相同規格計費，卻不服務任何流量。這就是 active-passive 的閒置成本：備援存在、隨時準備接手，但平時純粹在燒錢等 failover。active-active 的冗餘資源閒置成本較低——那些資源平時就在分攤負載、沒閒著——但代價換到了資料一致性的協調成本上。更便宜的是無狀態機群的 N+1／N+M：機群本來就多台在分攤流量，多備一兩台的開銷攤到整個機群、比例很小（<a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a> 有這個形態的說明）。所以 2x 不是一個固定數字，是「這份冗餘是整份閒置的熱備、還是機群裡多備的幾台」決定的：閒置的熱備付全額閒置成本，機群式的備援只攤到小比例開銷。</p>
<h2 id="用停機代價衡量值不值得">用停機代價衡量值不值得</h2>
<p>判斷冗餘值不值得，用的是過度配置的經濟學——過度配置的成本好算、配置不足的代價難算，兩者的平衡點就是該投多少，完整的算法在 <a href="/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型</a> 展開過。套到高可用上，這個平衡點由停機代價定：關鍵服務的停機代價極高——電商每分鐘宕機對應可估算的營收損失——所以值得付 2x 甚至更多；非關鍵服務停機代價低，貼近最低配置跑就好。同一套判準，關鍵服務算出來要厚冗餘、非關鍵算出來可以薄，差別在停機的代價不同。</p>
<h2 id="可用性等級是一道成本階梯">可用性等級是一道成本階梯</h2>
<p>可用性不是連續的旋鈕，是一道階梯——每往上一級，成本與複雜度同步階梯上升。單一可用區是一級、跨可用區（multi-AZ）是一級、跨區域（multi-region）又是一級。多數服務的合理路徑是先把單一區域的 multi-AZ 加備份做扎實，再評估要不要跨區域，依據是業務對「整個區域級故障」的容忍度。</p>
<p>跨區域這一級的決策特別要注意：它通常是合約 SLA 驅動的、不是技術判斷驅動的。一個 B2B SaaS 在合約裡承諾了某個可用性等級，跨區域投資才容易成立；純技術上「想更穩」很少足以正當化跨區域的成本與複雜度。可用性的頂級是有代價的錨——有平台跨 15 個區域做到 99.999%（一年停機約 5 分鐘），那個數字背後是十幾個區域各自維護的基礎設施。要不要爬到那一級，看的是合約與業務、不是工程的完美主義。</p>
<h2 id="冗餘成本要有護欄">冗餘成本要有護欄</h2>
<p>為可用性花錢也會失控，要有護欄。最典型的護欄是自動擴縮的成本上限——它是財務上的斷路器（<a href="/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型</a> 講過），設無限大就等著一次異常把帳單炸掉。高可用的投入同理：冗餘、備援、跨區複製每一項都要有成本上限，否則「為了更穩」會變成一個無底洞。可用性投資要跟一個明確的成本天花板綁在一起，超過就回頭重新評估這一級到底值不值得。</p>
<h2 id="沒驗證的冗餘等於白付">沒驗證的冗餘等於白付</h2>
<p>最後一筆容易漏算的成本是驗證。冗餘、DR、failover 都要靠演練驗證才算數，而演練要投入工程時間——這是高可用成本的一部分，不是額外選項。一個沒被 drill 驗證過的 multi-AZ、一份沒被 restore 過的 backup，是紙面上的冗餘：帳單上付了 2x，但真出事時它不一定接得住，等於白付了那筆冗餘成本。算高可用的總成本，要把「持續驗證的工程投入」算進去——冗餘的錢加上驗證的工，才是它真正的價格。省掉驗證的那份冗餘，是最貴的一種，因為它讓人以為有保障、實際沒有。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>過度配置的經濟學、autoscaler 的成本斷路器 → <a href="/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">模組五 成本模型</a></li>
<li>冗餘怎麼擺、2x 從哪來 → <a href="/blog/operations/06-high-availability/redundancy-patterns/" data-link-title="冗餘設計模式" data-link-desc="在 active-passive、active-active、multi-region 之間選冗餘模式時，用資料同步方式與 standby 是否服務流量來區分，並知道冗餘不等於備份">冗餘設計模式</a></li>
<li>驗證冗餘的演練節奏 → <a href="/blog/operations/06-high-availability/disaster-recovery/" data-link-title="Disaster recovery 策略" data-link-desc="設計災難復原時，先確認恢復路徑走得通再談 RTO/RPO、用 restore drill 把估值變量值、以及知道恢復不是切回流量就結束">Disaster recovery 策略</a></li>
<li>完整的雲端成本治理 → <a href="/blog/operations/08-cost-management/" data-link-title="模組八：成本管理" data-link-desc="雲端帳單怎麼不失控 — reserved instance、spot instance、right-sizing、成本監控告警">模組八 成本管理</a></li>
</ul>
]]></content:encoded></item></channel></rss>