早在2015年的時候,隨着阿里雲業務日新月異的發展,SQLServer業務也積累了大批忠實客戶,其中一些體量較大的客戶在相似大促的業務高峯時RDS的單機規格(規格是按照 內存CPUIOPS 必定比例分配,根據底層資源不一樣都會有各自上限)已經不能知足用戶的業務需求,在咱們看來也須要作Scale Out了,但SQLServer並無完備的中間件產品,因此不管是邏輯Sharding仍是隻讀分離,都須要用戶配合作應用改造,而從用戶角度看Sharding改動量很大不是一時間能完成的,那麼更多寄但願咱們提供讀寫分離的方案來知足業務需求。html
那麼讀寫分離咱們第一個想到的便是AlwaysOn技術,但因爲當時AlwaysOn對域控和Windows羣集都是強依賴,而這二者又對咱們所依賴的基礎設施有很大挑戰,須要作不少的突破產品限制的非標準化操做纔有可能實現而且還有安全風險,因此最後咱們只能放棄AlwaysOn技術方案,從新設計方案幫助用戶度過難關。sql
最後,面對這類客戶需求咱們的方案如何產品化是值得咱們思考的。數據庫
除了讀寫分離,產品上還有不少更重要的問題急需咱們去解決,因此從2015年到2017年咱們經歷了一個飛速發展階段,圍繞產品穩定性、多樣性以及用戶體驗作了很是多的事情,舉幾個點:安全
在這當中依舊不斷有讀寫分離的用戶需求,每次遇到咱們都先引導到了IaaS層用ECS自建實現,由於PaaS化的時機並不成熟,具體緣由跟SQLServer當前的技術棧和雲產品的結合有着密切的關係,這裏也能夠把咱們背後的一些思考分享出來。網絡
首先明確咱們討論的讀寫分離是什麼,MySQL的讀寫分離大部分是利用中間層作路由解析,基本上能夠實現對應用端透明只有少部分場景須要用戶作適配。架構
SQLServer並無成熟的中間件產品,本質上講是TDS(Tabular Data Stream)不徹底開放的緣由,若是要作也是有辦法的,只是投入的成本遠大於收益;基於此,SQLServer不管利用當前何種技術實現讀寫分離,對應用來說都須要作一些適配,即便是使用AlwaysOn技術在連接驅動的參數配置上也會不一樣,因此咱們後面討論的讀寫分離都是基於這個前提。運維
咱們對比了SQLServer全部相關的技術棧異步
其中數據安全、HA(High Availability 高可用)、DR(Disaster Recovery 災難恢復)以及備庫是否可讀是咱們最關注的;這裏的HA是指原生技術自己是否支持自動HA,當結合了部分雲產品後咱們也有能力把不支持變爲支持,數據安全和災難恢復的時間基本是原生技術決定的,備庫是否可讀是對單一技術的說明但作一些技術組合是能夠把不可讀變爲可讀的(好比Database Mirroring+Database Snapshots),最終綜合來看Transactional Replication和AlwaysOn是咱們以爲有機會作讀寫分離產品化的技術。分佈式
接着咱們單獨來看這兩種技術對比工具
原理上講Replication是邏輯複製,對比AlwaysOn的物理複製在性能、延遲、可靠性上都會有必定的差距;而且在產品複雜度讀、可控性上和易用性上,因爲Replication過於靈活細到表、列級別很難控制,不管用戶使用仍是咱們作產品化整個複雜度很是高;因此最終咱們選用AlwaysOn。
AlwaysOn是原生支持High Availability和Disaster Recovery的技術,自己又分爲Failover Cluster Instances(後續簡稱FCI)和Availability Groups(後續簡稱AG),下面的圖是FCI和AG的基礎架構
其中FCI和常規版本的AG都依賴Windows Server Failover Clustering(後續簡稱WSFC),不一樣點是FCI是Share Storage而AG是Share Nothing,FCI是實例級別同步而AG是DB級別,那麼很容易想到Share Nothing會有同步和異步的區別(和鏡像技術相似),其中二者的區別點須要咱們知道AlwaysOn的基本同步過程
首先在Primary節點的日誌(Commit/Log Block Write)會從Log Cache刷到磁盤,同時Primary節點的Log Capture也會把日誌發送到其它全部Replica節點,對應節點的Log Receive線程把收到的日誌一樣從Log Cache刷到磁盤,最後會由Redo Thread應用這些日誌刷到數據文件裏。
這其中還有一步,就是在Secondary端刷日誌的時候,若是Primary節點等待此次返回的Acknowlege Commit,那麼就是同步模式,反之若是Primary端不等Secondary的返回那麼就是異步模式,二者的區別由此展開。
這是基本的同步過程,但不管是AlwaysOn仍是Database Mirroring都存在一種狀況,即同步模式下若是Secondary端異常,Primary端沒有收到他的心跳也沒有收到此次的Acknowlege Commit,那麼也並不會算做寫入失敗,由於它一旦認定Secondary異常就不會等此次ACK,而是退化爲相似異步的模式,但會把Secondary端的異常狀態記錄在基表裏,經過相關視圖(sys.dm_hadr_database_replica_states、sys.database_mirroring)暴露出來,就是咱們常見的NOT SYNCHRONIZING/Disconnect狀態,這時候自動化運維繫統或者DBA就須要作判斷處理,等到Secondary修復從新聯機後會向Primary報告End of Log (EOL) LSN,Primary端再向它發送EOL LSN 以後hardened的全部日誌,一旦Secondary端開始接收到這些日誌並逐步刷到日誌文件中,那麼整個AG或者Mirroring相關的視圖又會標記其狀態爲Synchronizing,代表正在追趕直到Last Hardened (LH) LSN達到主備一致狀態,這時從新回到同步模式。
之前的狀況一直是這樣,直到SQLServer 2017 CU 1引入了REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT這個參數,參數名字很長但也基本包含了他的做用,應對剛纔的場景是可讓Primary端一直等到Secondary節點從新聯機並同步後在提供服務。
瞭解了AG同步、異步以及FCI,在總結下咱們關心的點
在實際方案中這些也能夠結合起來,最終再和阿里雲產品整合作一個總體方案,以前也講到阿里雲從15年就開始作相似方案來解決用戶問題,一直到最終PaaS化也過分了三個版本。
初版本咱們使用了ECS、SSD雲盤、OSS、VPC、SLB做爲基礎;在SQL技術上,咱們使用SQL+WSFC+AD的方式,目前看這種方式支持的版本也很是多,從12到17均可以;驗證方式既能夠用域控也能夠用證書。
但他有2個缺點:第一是成本高,除了Primary和兩個Secondary節點還要有兩個AD節點,畢竟咱們每一個環節都要保證高可用;
第二點是穩定性不夠,網絡抖動的狀況很是容易讓WSFC判斷異常,SQL端DB同時出現不可用;
這是第二版的架構,跟初版相比咱們用到了HAVIP來解決監聽器問題,去掉了AD只能用證書作驗證,但也所以最小資源開銷下降到3;這個方案也是以前在阿里雲上用的比較多的,但同第一個方案同樣,在網絡穩定性上會有不少挑戰,由於咱們將來面對的場景不僅是同城跨可用區還會有更多跨Region以及打通海外的場景,因此這個方案也只能Cover一部分用戶的需求,但對咱們不是一個最終方案。
最終咱們找到了方案三,去除了WSFC和AD,只關注基礎雲產品和SQL自己;最終要的是跟方案二相比,對網絡的抖動敏感度會更低也更可控,最可能是在Primary端出現Send Queue的堆積,這個咱們徹底能夠經過SQLServer相關的Performance Counter監控並作一些修復調整。
但沒有方案是完美的,可控性強的代價是這種無羣集無域控架構原生是不具有HADR能力的,這點熟悉WSFC的同窗能夠知道以前架構的HA都是依賴WSFC,他包括健康檢查、資源管理、分佈式元數據通知維護以及故障轉移,因此這時候就必須咱們本身去解決這個問題;爲此咱們也作了不少努力,最終實現了支持AlwaysOn無域控無羣集的HA系統,不依賴Cluster徹底自主可控的HA。
最終的產品架構以下,首先會保證有2個同步節點作主備,而且儘可能分配在不一樣的可用區,其它只讀節點默認是異步,最多能夠有7個只讀節點;用戶的訪問鏈路能夠有三種:
至此SQLServer AlwaysOn已經在阿里雲PaaS化,固然目前只是支持最主要功能,後續還有不少能夠完善豐富的地方,但願有更多用戶瞭解和使用這個產品並幫他們解決實際問題。