做者:郭憶sql
本文由 網易雲 發佈。
SQL Server 是 windows 平臺 .NET 架構下標配數據庫解決方案,與 Oracle、MySQL 共同構成了 DB-Engines Ranking 的第一陣營,在國內外企業市場中有着普遍的應用。
Mirroring 是 SQL Server 最經常使用的高可用解決方案,具備自動故障轉移,高安全模式下具備數據「零」丟失,對客戶端透明等優點,目前多家大的雲計算廠商均採用該技術實現雲端 SQL Server 高可用部署。今天,咱們就來聊聊 SQL Server 高可用鏡像實現原理。
數據庫
鏡像技術實現了位於不一樣物理服務器上的兩個 SQL Server 實例數據同步,在鏡像集羣中, SQL Server 實例具備三種角色:
○ Principal:具備完整的數據副本,對外提供數據庫讀寫服務;
○ Mirror:具備完整的數據副本,自己不提供讀寫服務,經過接收來自 Principal 的更新日誌實現數據同步,容許建立快照實現報表;
○ Witness:自己不存儲數據,只負責在高安全運行模式下提供自動故障切換的能力,確保兩個 SQL Server 實例只有一個對外提供服務,避免腦裂狀況出現;
windows
在鏡像集羣中,principal 和 mirror 的數據同步是依靠事務日誌來實現的,與 Oracle 和 MySQL 不一樣,SQL Server 的事務日誌是 Database 級別的,不是實例級別的,每一個 Database 都單獨的事務日誌,這也就使得 SQL Server 的鏡像是能夠基於 Database 層面實現。
一個 SQL Server 實例中的兩個 Database,一個能夠做爲 principal,一個能夠做爲 mirror,分別與其餘 SQL Server 實例組建鏡像關係;另外,SQL Server 一個 Database 只能有一個 mirror 節點,一個 mirror 的 database 不能夠再有 mirror 節點,這點與 MySQL 級聯複製不一樣;
後端
SQL Server 的事務日誌是物理記錄級別的,記錄了對數據庫某個頁的某行記錄(slot)的操做,principal 建立鏡像後,會啓動一個單獨的事務日誌發送線程,維護一個虛擬的發送隊列,而後讀取事務日誌,將其進行壓縮,根據官方公佈的測試數據,壓縮比不低於12.5%,而後發送給 mirror 節點,mirror 節點接收到之後,會將其寫入本地在磁盤上的一個重作隊列文件中,而後再經過另外的一個線程異步的方式,從重作隊列中獲取事務日誌,而後分發給應用線程(process unit)進行回放。
不一樣於 MySQL Binlog,因爲 SQL Server 的事務日誌在 principal 上事務執行過程當中就已經源源不斷的寫入(MySQL Binlog 僅在事務提交階段生成),在 principal 事務執行的同時事務日誌就已經傳遞給了 mirror,因此基於事務日誌的 SQL Server 的複製性能會更理想。同時,在 mirror 回放的過程當中,能夠基於頁(page)級別進行併發更新(redo parallel),在 SQL Server 的標準版中,僅提供一個線程進行事務日誌回放(roll forward),在企業版中,若是當前服務器 CPU 大於5核,則每4個核,增長一個並行線程,若是低於5個核,則仍然使用單線程回放。同時,基於頁的事務日誌的併發執行,還有一個好處就是對於同一個頁面的更新能夠合併刷新,減小髒頁刷新數量。
緩存
鏡像集羣提供了三種運行模式:
○ 高性能模式:principal 與 mirror 之間數據異步傳輸,principal 上的事務提交無需等待 mirror 的響應,principal 宕機後,存在數據更新丟失的可能,不支持自動故障轉移,能夠經過強制服務的方式使得 mirror 提供服務。適合對數據可靠性要求不高,性能要求較高的業務場景,與 MySQL 的異步複製模式,Oracle DataGuard 最大性能模式相近;
○ 不帶故障轉移的高安全模式:principal 上全部的事務提交,都必需要確認該事務涉及的事務日誌均已經傳送到的 mirror 上,並寫入 mirror 的重作隊列中,持久化(是否持久化到外存設備還與 windows 操做系統寫入緩存策略相關),mirror 返回確認後,纔可提交,能夠實現 principal 宕機下數據「零」丟失,不支持自動故障轉移,能夠經過手動轉移或者強制服務方式使得 mirror 提供服務。與 MySQL 5.7 Loss-less replication、Oracle DataGuard 最大可用模式相近;
○ 帶故障轉移的高安全模式:與不帶故障轉移的高安全模式相比,增長了 witness (見證服務器),能夠實現自動的故障轉移,經過 witness,能夠確保只有一個節點成爲 principal,對外提供服務,實際上 witness 最重要的一個做用就是選主;
安全
鏡像集羣故障轉移最複雜場景就是帶見證服務器的支持自動故障轉移的高安全模式,因此咱們重點討論該模式下的故障處理流程。
初始狀態下,witness、principal 和 mirror 三個節點兩兩之間均保持長鏈接會話,如今討論其中一方鏈接中斷的狀況:
服務器
此時 witness 與 mirror 鏈接正常,觸發自動故障恢復流程,principal 丟失 witness 鏈接會話,若是 principal 仍在運行狀態,則將狀態標記爲 disconnected,表示失去與 mirror 鏈接,切斷全部客戶端鏈接,中止讀寫服務,等待故障切換。爲了防止網絡抖動引發沒必要要的切換,會話超時默認時間爲 10秒;witness 和 mirror 將 principal 標記爲不可用,等待 mirror 上的重作隊列中的事務日誌回放(roll forward)完成後,mirror 成爲新的 principal,開始對外提供讀寫服務。
網絡
最後 mirror 會經過後臺線程,將未提交的事務回滾(基於 binlog 的 MySQL 複製,因爲 binlog 是在事務提交階段生成的,因此不存在事務回滾的階段)。
從整個故障切換的流程來看,故障切換時間主要包括三個部分:檢測到 principal 宕機的時間、mirror 上重作隊列中事務日誌的回放時間以及回滾未提交事務的時間,其中前面兩段時間服務不可用,尤爲是重作隊列的回放時間,直接決定了服務不可用時間。
架構
此時,principal 與 witness 鏈接正常,principal 狀態變爲 Disconected,表示終止與 mirror 鏈接,mirror 狀態變爲 suspend,principal 再也不向mirror 發送事務日誌,等待 mirror 從新創建到 witness 鏈接後,principal 纔會恢復與 mirror 進行數據同步。
併發
principal 與 mirror 同時保持 witness 的鏈接會話,可是 principal 與 mirror 之間會話中斷,witness 會通知 mirror,principal 依然保持鏈接狀態,不會觸發故障切換;此時 principal 因爲保持有 witness 的鏈接會話,服務正常。
下面來考慮三方會話兩個會話同時中斷狀況:
只要 mirror 與 witness 會話正常,便可完成正常的故障轉移;若是 mirror 與 witness 鏈接也中斷,則沒法完成,即使是後來 mirror 與 witness 的會話優先恢復,則也沒法故障切換,由於已然不肯定 mirror 是否擁有所有 principal 的數據,此時即使 principal 處於運行狀態,也沒法提供服務,等待 principal 與任意節點會話恢復正常,便可恢復讀寫服務;
不會觸發故障切換,principal 切入公開運行模式(異步),即不會再向 mirror 發送事務日誌,也再也不須要等待 mirror 的響應,直到 mirror 從新恢復會話。
不會觸發故障切換,principal 繼續提供讀寫服務,與 mirror 數據繼續同步,鏡像集羣喪失自動故障轉移能力,退化爲不帶故障轉移的高安全模式;
若是三方會話同時鏈接中斷,則 principal 沒法提供服務,直到 principal 與任意節點通訊恢復正常。
場景1中,初始狀態實例 A、B 和 witness 保持會話鏈接,其後,A 實例宕機,失去與其餘成員的會話,實例 B 與 witness 保持會話,觸發故障切換,實例 B 升級爲 principal。其後實例 B 也宕機,服務中止。而後實例 A 恢復,可是因爲此時實例 A 已是 mirror,不能肯定實例 A 擁有實例 B 的全部更新數據,因此沒法故障切換,最後實例 B 恢復,服務恢復正常。
場景2 中,實例 A 和 B 同時失去了與 witness 的會話,可是服務已然正常,A 與 B 之間數據繼續同步,其後 A 與 B 同時宕機,服務中止。最後 A 恢復服務,與 witness 恢復會話,A 繼續提供服務。
一個完整的高可用機制除了後端節點的切換,還包括髮生故障轉移後,客戶端如何可以快速地鏈接到冗餘節點,繼續業務讀寫。經常使用的實現,包括 Driver 層解決方案,例如 mongoDB replication set,也有經過二層內的廣播方式實現 vip,例如 keepalived,固然還包括 proxy,以及三層 DNS 的實現。
SQL Server 的實現採用了 Driver 層處理的方式,開發者要實現自動的故障轉移,在鏈接數據庫時,除了必需要指定初始節點的 IP 和端口,還要指定故障轉移的節點的 IP 和端口。客戶端首先嚐試使用初始節點建立鏈接,若是初始節點指向的實例當前爲 principal,則鏈接會創建成功,能夠正常的讀寫。當發生故障切換時,principal 會切斷全部已有客戶端鏈接,而後客戶端創建到初始節點鏈接也會失敗,經過必定的重試策略失敗後,會嘗試鏈接以前指定的故障轉移節點,從而實現服務入口的切換。
SQL Server 經常使用的訪問接口:OLE DB、ODBC、ADO 均支持指定故障轉移節點,格式以下:
Server=250.65.43.21,4734; Failover_Partner=250.65.43.22,4734;
鏡像集羣的監控能夠經過 SQL Server Management stdio 啓動鏡像監視器,或者系統內置的存儲過程來實現,監控的主要指標包括:
○ 未發送日誌:principal 上未發送的日誌超過指定的閾值,會在 principal 上生成一個警告,在高性能模式下,強制服務時能夠做爲評估 principal 上事務丟失數量的依據,一樣也適用於在高安全模式切換成異步模式狀態下(mirror 失去鏈接)。
○ 未還原日誌:重作隊列中的未被應用的事務日誌數量(KB),超過閾值,會在 mirror 上生成一個警告,該值能夠做爲評估故障轉移時間的主要因素。
○ 最先未被髮送的事務:principal 發送隊列中,最先未被髮送的事務距離如今的時間,單位時分鐘,超過閾值,會在 principal 上生成警告,與未發送日誌量一塊兒,從時間維度,衡量高性能模式下和高安全異步模式下,數據丟失數量。
○ 鏡像提交開銷:高安全模式下,principal 上事務從提交到等到 mirror 響應的時間開銷的平均值,若是超過閾值,則在 principal 上生成一個警告,在同步模式下,該值能夠衡量同步開銷。
參考文檔:請點擊這裏
瞭解網易雲:
網易雲官網:https://www.163yun.com/
新用戶大禮包:https://www.163yun.com/gift
網易雲社區:https://sq.163yun.com/