這裡都是我的經驗,沒有實際操作與技術,主要是在真的去做之前,要先了解的東西,而這些東西跟技術無關
實際操作會在下一篇
真正的可用性要從使用者角度去看
如果今天SQL Server 都沒有掛掉,但是網路斷了、應用程式服務掛了,那對使用者來說還是一樣不能用。
但是其他層面的問題不在這裡討論,我們只專注在保證 SQL Server 上。
在可用性的時候我們有一個標準,就是幾個 9
| Availability | 一年允許停機大約多久 |
|---|---|
| 99% | 約 3.65 天 |
| 99.9% | 約 8.76 小時 |
| 99.99% | 約 52.6 分鐘 |
| 99.999% | 約 5.26 分鐘 |
5個9 只能停機五分鐘
這很困難,以下任一狀況發生都會直接破功
Windows patch 重開機
SQL Server failover 太慢
網路設備故障
Storage 出問題
人為操作錯誤等等
可是這只是基礎這樣分,如果可以接受一年停機 8.76 小時,可是每天都固定會停機三分鐘,那這也是不能接受的。
所以在開始操作 HA 之前,要先去了解公司或是客戶可以接受的水準例如
SQL Server 一年可用性必須達到 99.9%
單次故障最多 1 小時內要恢復
資料最多只能遺失 15 分鐘
如果沒做到,廠商要賠錢或扣款
而為了達到這個目的
假設要做到 99.999%,需要買第二台 SQL Server、第二套 Storage、Always On、監控、備援機房。
然後要考慮
這個錢值得花嗎?
業務真的需要這麼高的可用性嗎?
如果一年停 2 小時,我們能不能接受?
這都是在 HA 之前要先去了解的,然後再往這個目標前進。
有長時間的更新 Service Pack 也要考慮進去。
備份的資料是存在哪? 從哪裡拿回來的時間? 硬碟故障執行 chkdsk 時間? 這些都要考慮
跟使用者溝通停機成本,基本上在公司角度,通常得到的答案都是 0
要保證零停機時間是不可能的,即便是用雲端,也不太可能保證永遠 0
以我跟使用者或公司溝通的經驗來說這會有兩種成本
有形成本
無形成本
有形成本 :
這比較容易計算,以銷售為例,最明顯的有形成本,就是因為銷售人員無法接單而造成的營收損失。
無形成本 :
這就很難量化,但可能會昂貴更多。例如,如果客戶無法向你的公司下訂單,他們可能會改向競爭對手公司下訂單,並且再也不回來。其他無形成本可能包含員工士氣下降,進而導致員工流動率升高,甚至是公司聲譽受損。
所以我通常,在計算無形成本的時候,會把有形成本 * 3 來估算。
假設停機一小時會損失兩千美金,應用程式生命週期為三年,那麼可以算出停機成本(三年)
200033.65243 = 525600
然後可用性解決方案成本要去考量
硬體、授權、電力、佈線、額外儲存空間,以及其他額外支援設備,例如新的機架、管理成本等等
我都是用這種方式去估算,並且製作這個表格去跟公司說明,並且最後讓公司或客戶選擇他可以接受的放案。
| 可用性層級 | 一年允許停機大約多久 | 停機成本(三年) | 可用性解決方案成本 |
|---|---|---|---|
| 99% | 約 3.65 天 | $525,600 | $108,000 |
| 99.9% | 約 8.76 小時 | $52,560 | $224,000 |
| 99.99% | 約 52.6 分鐘 | $5,256 | $462,000 |
| 99.999% | 約 5.26 分鐘 | $526 | $910,000 |
最後備援有三種
| 類別 | 描述 | 範例技術 |
|---|---|---|
| 熱備援 | 一種已同步的解決方案,其中容錯移轉可以自動或手動發生。通常用於高可用性。 | 叢集、AlwaysOn 可用性群組(同步) |
| 暖備援 | 一種已同步的解決方案,其中容錯移轉只能手動發生。通常用於災難復原。 | Log Shipping、AlwaysOn 可用性群組(非同步) |
| 冷備援 | 一種未同步的解決方案,其中容錯移轉只能手動發生。這只適用於永遠不會被修改的唯讀資料。 | — |
開始說明前,有幾個名詞要先了解
叢集 :
叢集是把多台伺服器組成一個受管理的系統,讓它們可以共同承載服務、互相監控,並在故障時由其他節點接手服務。
如果多台伺服器放在一起,但是他不能監控 Server 還在不在、不能判斷誰故障、不能判斷誰可以接手、不能把服務切到另外一台 Server等等的話,那這多台伺服器放在一起只能稱為群組。而提供這項服務的元件就叫做 cluster service。
叢集就是有包含上述幾種功能。
叢集並不是 SQL Server 專屬功能,他可以保護很多種服務,在 Windows 裡,這叫做 Windows Server Failover Cluster ( WSFC )。
而 SQL Server 就是利用 WSFC 來做高可用性。
SQL Server 會利用 WSFC 做裁判,來判斷服務還在不在、判斷誰可以接手、把服務切到另外一個可以接手的地方。
那你現在要跟我說啊我要是不是 windows server 怎麼辦,那我只能跟你說,一開始就有叫你用 windows,當然 unix 也是有支援 ha,但是相容性或功能一定沒有 windows 來的好來的多,當然我也不會在 unix 上用 sql server,我會用 oracle、mysql。等到我開始寫 oracle 的時候再說。
節點 ( Node ) :
叢裡裡面,每一台伺服器都叫做節點。
第一層 : Windows Server
這是作業系統、實體機、VM
第二層 : WSFC
這是在作業系統上的一個服務,負責節點偵測、Quorum、Witness、Failover、資源切換
第三層 : SQL Server
這裡就是我們最在意的服務
先分清楚這三層之後才有辦法理解整個架構
Windows Server = 機器本體
WSFC = 叢集裁判
SQL Server = 被保護的服務
在架構上如果有兩台伺服器為叢集,這兩台上面都會有一個 WSFC 的服務,這個服務會一直去聽另一台伺服器的心跳,只要他聽不到了,會認定對方死了,所以這邊要做相應的動作。
FCI 這是一個 SQL Server 提供的 HA 架構,但是他建立在 WSFC 這個服務上
因為 FCI 跟 WSFC 是互相合作的關係 所以才這麼說
FCI 是 SQL Server 的高可用性架構,
但它依賴 Windows Server Failover Cluster 來完成節點偵測、資源切換、IP/名稱切換、儲存體掛載。
Windows Cluster 負責:
SQL Server FCI 負責:
FCI 是一個可以在這個伺服器群組中移動的 SQL Server instance。
如果其中一台伺服器故障,另一台伺服器就會接手這個 SQL Server instance,這是 A / P 架構。
FCI 最適合用在高可用性情境,尤其是資料庫很大,或寫入量很高的系統。原因是 FCI 使用的是共用儲存體,資料只需要寫入磁碟一次。
相較之下,如果使用 SQL Server 層級的 HA 技術,例如 Availability Groups,寫入資料時,資料會先寫入主要資料庫,然後還要寫入次要資料庫。尤其在同步模式下,主要資料庫要等次要資料庫也完成寫入後,commit 才算完成。這可能造成效能問題。
主動主動是在說有兩台 SERVER 上面都各自有 INSTANCE 在跑
並且互為叢級
這種架構要很小心資源,這個問題在記憶體最佳化的時候,有講過
例如
Node1:128GB RAM
Node2:128GB RAM
平常
Instance1 在 Node1 用 96GB
Instance2 在 Node2 用 96GB
如果今天 INSTANCE 1 掛了,切到 node2
那 node2 上面總共就需要 96+96=192 gb 的 ram
可是他本身只有 128 gb ,那 node2 也會撐不住,導致兩個 INSTANCE 都出問題
這種架構還有一個要理解
他並不是一個 INSTANCE 在兩個 NODE 上面跑,各分 5050的流量
他是一個 NODE 上面一個 INSTANCE,並沒有辦法分兩個NODE去跑 5050流量。
這種架構,基本沒有任何好處,你說要省錢嗎? 但是為了避免剛剛舉例那種爆 RAM 的事情,所以在設定的時候還是會限制最大 RAM 的使用量,這樣等於平常那些 RAM 也白費。
這在我看來是一個浪費錢、浪費時間也沒有什麼保障的功能。
一組叢級最多可以有 64 個節點。
如果在一個環境中有超過三個節點的話,不可能說設定成 1 個主動,剩下備援,這樣太浪費成本。
N + 1
只留一個節點當備援,其他節點繼續主動。
優點是省錢,缺點是如果多重故障發生,這個備援也沒有用,因為會扛不住
N + M
留多個節點當備援可以解決上面的問題
這個做法會更加彈性
我可以 node1 永遠去 備援1
node2、node3 永遠去 備援2
可以這樣隨便指定。
這東西是為了讓故障發生時,自動移轉可以發生,叢級服務必須知道節點是不是已經故障了。
為了達成這個目的,每個叢集結點都會有一個投票權,去產生一個仲裁結果,仲裁伺服器會去見證某個節點,然後投票。
超過半數的投票成員認為無法與節點通訊,那叢級服務就會認定故障,並且開始進行移轉。
例如在上面,什麼叫做 Node 壞掉? 的那個例子裡面 :
第一點壞掉那無庸置疑,沒什麼好說的
但如果是第二點呢? 叢集之間網路斷掉,彼此都認為對方已死,我必須啟動服務,會造成什麼結果?
兩個服務同時起來,這有可能會造成衝突等等,而且這也不是我們想看到的結果。
所以這時候就會有一個仲裁伺服器,在第三方的角度去看,他去看到底是不是有人真的壞掉,並且去投下最後一票看是哪一邊的服務要起來,用這種方式去達成過半數票。
仲裁伺服器同時也會看,你們這兩個是真的有人死掉,還是只是你們兩個無法溝通;只是無法溝通的話那也不需要做到移轉。
超過半數這個設計是為了避免 split-brain
假設有兩資料中心
資料中心 1 有 3 個 Node
資料中心 2 有 3 個 Node
兩個資料中心之間網路斷線,但其實這六個節點都還在線上
這會導致叢級兩邊認為對方都不可用
如果這時候沒有超過半數投票的這個設計,會導致兩邊都覺得我應該要拿到對方的控制權。
因為兩邊都是三票
所以才要有過半數的設計。
所以基於這層理由
叢級如果是基數節點,那就讓他們自己去投票
如果是偶數節點而且有共用磁碟,就在共用磁碟上新增一個 witness ,讓他也加進來投票。
如果是跨站點叢級,那就node + file share withess
如此可以保證,有問題時,一定有邊投票可以分出勝負。
當然還有一個做法,因為現在是每個節點一人一票,也可以手動去把某個節點票數歸0,如此也可以達到目的。
file share withness 他不是真的 node,他只是一個驗證、幫忙投票的東西而已。
不過,這個會遇到一個問題 partition in time,時間點上的斷層
舉例來說
node1 正常
node2 重開機,正在跟 node1 同步最新的 cluster database
file share witness 正常
但此時發生,node2 尚未同步完成,node1 突然掛掉。
那會造成 file share witness 現在去看沒有一個節點是正常的
整個叢級就死亡
所以又有一個問題了,按照剛剛的說法,那就會有一個情況
假設有兩個節點與一個 File Share Witness:
Node1 的 SQL Server 壞掉,但 Windows Server 與 Cluster Service 仍然正常,而且 Node1 可以連到 Witness。
Node2 的 Windows Server、Cluster Service、SQL Server 都正常,但 Node2 無法連到 Node1,也無法連到 Witness。
此時從仲裁的角度來看:
Node1 仍然是一個有效的 Cluster Node,因此 Node1 自己有 1 票。
我上面雖然寫 witness 會去看誰死了,但其實 Witness 並不是主動去判斷誰死了,而是誰能連到它,誰就能取得 Witness 這一票。
因此 Node1 + Witness = 2 票。
Node2 雖然 SQL Server 是正常的,但它只能看到自己,所以只有 1 票。
總票數為 3,過半數為 2。因此 Node1 所在的 partition 有仲裁資格,而 Node2 所在的 partition 沒有。
這表示 Node1 這邊有資格繼續管理叢集資源,而 Node2 即使 SQL Server 正常,也不能自行接手資源。
如果 Node1 上的 SQL Server Resource 已經故障,Cluster 可能會嘗試在 Node1 上重新啟動 SQL Server Resource;如果無法成功,而 Node2 又不在有仲裁的 partition 裡,那 SQL Server 服務可能仍然無法恢復。
因此,仲裁的目的不是選出 SQL Server 正常的節點,而是先確保叢集不會發生 split-brain。Cluster 的原則是:寧可服務停機,也不要讓兩邊同時啟動同一個叢集資源造成資料損毀。
比較新的 windows server 會支援 動態仲裁,根據節點數量自動決定是否給仲裁 witness 一票,所以比較新的 server 比較不用擔心平票的問題。
首先這也是 SQL Server 功能,但是他跟 FCI 一樣也依賴 WSFC
不過他跟剛剛講的 FCI 不一樣的地方是,FCI 是共用硬碟,資料近來只需要寫一次,整個叢集會共用那一份。
而 AOAG 則是資料進來會被送到所有叢集結點上都寫一份。
AlwaysOn 可用性群組取代 Database Mirroring,本質上可以視為 Database Mirroring 跟 Clustering 技術的結合。
Database Mirroring :
這是 SQL Server 以前的一種資料庫高可用性技術
首先 SQL Server 會以獨立 instance 的方式安裝在叢集 node 上
然後會在叢集上安裝一個支援叢集的應用程式,Availability Group Listener,以用來將留量導向正確的節點。
同時 AOAG 不依賴共用磁碟。他會壓縮 log stream,並將其傳送到其他節點,方式類似 Database Mirroiring。
當資料庫較小,而且寫入量較低時,AOAG 是很適合用來實作高可用性的技術。
原因是:如果使用同步模式,資料必須先在所有同步複本上完成 commit,然後 primary database 的 commit 才算完成。
單純的 AOAG 架構最多可以有 8 個 replica,其中包含 3 個同步 replica。
一個 Primary Node
三個 同步 Node
五個 非同步 Node
先說結論 AOAG 會比 FCI 更適合在虛擬環境中使用。
如果是 FCI 架構,因為共用硬碟的關係,雖然還是可以在虛擬化環境中使用但是會限制很多 VM 功能,例如在 VMware 環境中,如果 VM 使用透過 Fiber Channel 呈現的 shared disk,無法同時使用 vMotion 或 DRS。vMotion 是用來將 VM 從一台實體主機移動到另一台實體主機;DRS 則是根據實體主機的資源使用情況,自動調整 VM 所在的位置。
上面各種虛擬環境的功能具體是做什麼不清楚、名詞看不懂沒關係。只需要知道這代表如果 SQL Server 採用 FCI 架構,雖然仍然可以部署在虛擬化環境中,但因為 shared disk 的限制,可能會犧牲部分 VM 遷移、自動資源調度、快照或備份整合等功能。
相較之下,AOAG 不需要 shared disk。每個 replica 都有自己的資料庫副本,資料是透過 transaction log 從 primary replica 傳送到 secondary replica。因此,AOAG 比較符合虛擬化環境中「每台 VM 使用自己獨立磁碟」的設計,也比較不容易受到 shared disk 限制影響。
所以在虛擬化環境中,如果希望保留較完整的 VM 管理能力,例如 vMotion、DRS 或其他虛擬化平台功能,AOAG 通常會比 FCI 更適合。
VMware 功能對 shared disk 的限制,可以透過將儲存體直接以 iSCSI 連線呈現給 guest OS 來繞過,但代價是效能會下降。
如果現在當你有主動式 failover 需求,但不需要 log delay 時,AOAG 是非常適合用於災難復原的技術。
故意延遲有時候是為了避免遇到人為錯誤或邏輯錯誤才故意的,例如有人不小心刪掉某個表,我在傳 log 給複寫的 instance 的時候,可以故意設定 30 分鐘後才套用。
但是 AOAG 的設計目的就不是這樣,他設計目的就是 Primary 變更就盡可能快速的套用到 Secondary。
AOAG 最在意的是,今天 Primary 掛掉,Secondary 能不能以最快的速度接手。
所以沒有故意 delay 的需求的話,AOAG 非常適合。
另外有需要故意 delay 的話,可以選擇 log shipping 的方式。
AOAG 的 Secondary 也不一定要等到災難發生才能使用。
因為他獨立硬碟的特性,所以他可以用來當作報表等等,只負責查詢功能工作的 instance。他可以允許你去設定 Secondary 成唯讀狀態。
相比於 FCI 架構,就不會平常沒事的時候把伺服器擺在那邊浪費。
但是,設定成自動 failover 的目標跟拿來跑報表 / 查詢的不能同時是同一台。
其實是可以同一台,並沒有技術上的限制,但我不建議。
應用程式在開發的時候,其實也不需要特別判斷我只要讀取的話我要去連哪一台 SQL Server,只需要在 connection string 上面寫 only-read,AOAG Listener 就會自動把他導向可讀取的 secondary replica。
如果唯一的需求是讀取擴展,而不是 HA 或 DR,那麼也可以設定不使用 cluster 的 Availability Groups,也就是完全不使用 WSFC。
在這種情況下,不會有 cluster service,因此也不會有自動重新導向。Availability Group 內的 replica 彼此通訊時會使用憑證。
如果你在沒有 AD 的情況下設定 Availability Groups,例如 workgroup 或跨 domain,情況也是如此。
AOAG 在做 DR 時,會用非同步的方式去做,所以資料不是0遺失。
在這裡要說明 HA 跟 DR 的不同
這兩個都是一種可用性的設計策略
差別在於他們的目的不同,所以給兩個名字
正常來說,所有人終極目標,幾乎都是 HA 那樣
斷線後立刻接手、資料0遺失等等
但是有時物理限制會導致這無法實現,進而衍生出 DR 這個東西。
| 比較項目 | HA 高可用性 | DR 災難復原 |
|---|---|---|
| 核心目的 | 小故障時,服務盡量不中斷 | 大災難後,系統可以救回來 |
| 處理範圍 | 單台 Server 掛掉、SQL Service 掛掉、單一節點故障 | 整個機房掛掉、火災、地震、區域網路中斷 |
| 常見距離 | 同機房、同園區、低延遲環境 | 異地、跨縣市、跨區域、跨國 |
| 使用者感受 | 可能只中斷幾秒到幾分鐘 | 可能中斷幾分鐘到幾小時 |
| RTO | 通常很短 | 可以比較長 |
| RPO | 通常希望 0 或接近 0 | 可能接受幾秒、幾分鐘,甚至更久 |
| Failover | 常見自動 failover | 常見手動或半自動 failover |
| 同步方式 | 常用同步 | 常用非同步 |
| 為什麼 | 距離近,延遲低,可以等 Secondary | 距離遠,延遲高,不想拖慢正式交易 |
| 常見技術 | FCI、AOAG 同步模式 | AOAG 非同步模式、Log Shipping、Backup/Restore |
| 典型例子 | 台北機房 Node1 壞掉,Node2 接手 | 台北機房整個掛掉,台中機房接手 |
| 成本與複雜度 | 中高 | 高,尤其跨站點設計 |
| 主要風險 | Failover 失敗、資源不足、quorum 設計錯誤 | 資料落差、切換流程慢、演練不足、DNS/連線切換問題 |
這整個最大差別,就是距離。
我今天要台北跟台中機房做 HA 當然可以
但問題是這種距離下要做 HA,用 FCI 模式那問題來了,共用硬碟要放哪?
無論你放台北或台中,其中一方去讀硬碟一定會有網路延遲,造成效能降低,而且是降低非常顯著。
如果用 AOAG 同步模式,台北 COMMIT 前,要等台中也確認 LOG 寫入硬碟,這中間的網路傳輸造成的延遲,會讓整個應用程式變得更慢。更遑論跨國的 HA。
如果你有辦法做到克服距離、物理限制,那確實全部都用 HA 的角度去思考架設是最好的,但現實做不到所以有退而求其次的 DR 這個產物出現。
當用於 DR 時,AOAG 會以非同步模式運作。這表示在發生 failover 時,可能會遺失資料。RPO 並不是固定的,而是取決於最後一筆尚未 commit 的交易時間。
跟 FCI 不一樣,FCI 單位是 INSTANCE,切換的時候是整個 INSTANCE 一起切換。
AOAG 的單位是 Availability Group,切斷的時候是只切換群組。
然後可以去設定,那些 db 要放在這個 group 裡,然後真的要 failover 的時候,就只會把這群組內的 db 都轉切過去。
在一個 instance 上可以設定多少 Availability Group,沒有硬性限制;能參與 AOAG 的資料庫數量也沒有硬性限制。
不過,Microsoft 已測試並正式建議:每個 instance 最多 100 個 databases 與 10 個 Availability Groups。
擴展資料庫數量時,主要限制因素是 AOAG 使用 database mirroring endpoint,而且每個 instance 只能有一個 endpoint。這表示所有資料修改的 log stream 都會透過同一個 endpoint 傳送。
如果發生 PAGE 損毀,這個資料庫又設定在 AOAG 中的副本,那 SQL Server 會自己嘗試透過別的複寫取得該 page 來修復這個損毀。
這表示邏輯損毀可以被解決,而不需要你執行 restore,也不需要執行帶有 repair option 的 DBCC CHECKDB。
不過,自動頁面修復不適用於下列 page 類型:
結論就是它會自動修,這沒有什麼要注意的,因為他全自動。
他流程也沒有到很複雜,但我覺得不需要了解,只要記得會全自動修就好了。
這是一種 DR 技術
運作方式如下
就這麼簡單
因此這個很適合用來在需要 LOG DELAY 的 DR 環境裡面。
Log Shipping 從他的運作方式也可以看出來,他不是合用在 HA,因為他沒有自動 failover 功能。
Log Shipping 架構中,只會有一台主伺服器,其他的都是從伺服器。
但是跟 AOAG 一樣,他可以說這一台從伺服器做 DR、這一台從伺服器去做報表 ReadOnly
在備份還原的時候,一直有一個東西沒有講
就是在還原交易紀錄備份時,有一個參數可以設定 Recovery、NoRecovery、Standby
Recovery mode 會讓 database online。
但是 Log Shipping 不支援這種模式。
因為一旦 database recovery 完成、變成 online 狀態,就不能再繼續套用後續的 transaction log backup。
log shipping 需要一直繼續 restore 後面的 log backup,所以不能用這個。
NoRecovery mode 會讓 database 保持 offline,這樣後續還可以繼續 restore 更多 backup。
這是 log shipping 的正常設定,也是 DR 情境中適合的選擇。
Standby option 會讓 database online,但會是 read-only 狀態。
這樣你仍然可以繼續 restore 後續的 log backup。
在 log shipping 架構中,可以選擇性設定一台監控伺服器,用來幫忙監控跟蒐集告警。
但是,如果想用這個功能,就一定要在 log shipping 設定的時候一起設定好,事後想加的話沒可能,只能全部重做。
跟其他的架構不同,Log shipping 的 failover 比較多人工操作。
他這個就跟一般的備份還原一樣,只是會自動幫你交易紀錄備份還原到別的地方,實際發生要 ha 的時候,還是一樣要手動結尾交易紀錄備份,然後轉到新的 server 上,去還原然後上線。
為了滿足業務需求,是可以把上述這些技術進行組合的。
例如 FCI + AOAG 組合。
因為 FCI 不需要重寫一次資料,所以可以把 FCI 當作本地 HA,然後 AOAG 採用非同步方式做成異地 DR。
SQL Server 的 HA/DR 沒有單一標準答案。要先看 downtime 成本、SLA、RTO、RPO、效能、成本與架構限制,再決定要用 FCI、AOAG、Log Shipping,或把多種技術組合起來。
下一篇會開始實際操作 AOAG