久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

GitHub如何做好MySQL高可用性

176次閱讀
沒有評論

共計 7393 個字符,預計需要花費 19 分鐘才能閱讀完成。

這篇文章主要介紹了 GitHub 如何做好 MySQL 高可用性的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇 GitHub 如何做好 MySQL 高可用性文章都會有所收獲,下面我們一起來看看吧。

Github 使用 MySQL 數據庫作為所有非 git 事務的數據存儲。數據庫的可用性對 Github 的正常運行而言至關重要。無論是 Github 網站本身,還是 Github API,身份驗證服務等都需要訪問數據庫。Github 運行了多個數據庫集群用于支撐不同的服務于任務。數據庫的架構采用的是傳統的主從結構,集群中一個節點(主庫)支持寫訪問,其余的節點(從庫)同步主庫的變更,支持讀服務。

主庫的可用性至關重要。一旦主庫宕機,集群將不能夠支持數據寫入服務:任何需要保存的數據都無法寫入到數據庫保存。最終導致 Github 上任何變更,例如代碼提交,提問,用戶創建,代碼 review,創建倉庫等操作都無法完成。

為了保證業務的正常運行,我們自然需要在集群中有一個可用的支持寫入的數據庫節點。同時,我們也必須能夠快速的發現可用的可寫入服務數據庫節點。

就是說,在異常情況下,假如主庫宕機的場景,我們必須確保新的主庫能夠立刻上線支持服務,同時保證集群中其他節點能夠快速識別到新的主庫。故障檢測,主庫遷移以及集群其他數據節點識別新主庫的總時間構成了服務中斷的總時間。

高可用性的實現

當設計高可用以及服務發現系統方案的時候,從下面幾個問題出發,也許能夠幫助我們快速找到合適的解決方案:

最大允許的服務中斷的時間是多少?

服務中斷檢測的準確性怎么樣?是否能夠允許服務中斷檢測誤報(會導致過早故障轉移)?

故障轉移的可靠性怎么樣?什么情況會導致故障轉移失敗?

這個方案能否在跨數據中心實現,以及如何實現的?在不同的網絡狀況下會怎么樣,延遲高,或延遲低的情況會怎么樣?

這個解決方案能否承受整個數據中心(DC)的故障 或者網絡隔離的情況?

有什么機制防止 HA 集群腦裂情況(在一個整體的系統,聯系著的兩個節點分裂為兩個獨立節點,這兩個節點爭搶共享資源寫入數據的情況)?

能否容忍數據丟失?容忍丟失程度是多少?

為了說明上面的幾個問題,我們先來看一下我們之前的高可用方案,以及我們為什么要改進它。

摒棄基于 VIP 和 DNS 的發現機制

在之前的方案中,應用了下面的技術方案:

使用 orchestrator 作為故障檢測遷移方案。

采用 VIP 和 DNS 方式作為主節點發現方案。

客戶端通過節點名稱,例如 mysql-writer-1.github.net,解析成主節點的虛擬 IP 地址 (VIP),從而找到主節點。

因此,正常情況下,客戶端可以通過對節點名稱的解析,連接到對應 IP 的主節點上。

考慮夸三個數據中心的拓撲結構的情況:

一旦主庫異常,必須將其中的一個數據副本服務器更新為主庫服務器。

orchestrator 會檢測異常,選出新的主庫,然后重新分配數據庫的名稱以及虛擬 IP (VIP)。客戶端本身不知道主庫的變更,客戶端有的信息只是主庫的名稱,因此這個名稱必須能夠解析到新的主庫服務器。考慮下面的問題:

VIP 需要協商:虛擬 IP 由數據庫本身所持有。服務器必須發送 ARP 請求,才能夠占有或釋放 VIP。在新的數據庫分配新的 VIP 之前,舊的服務器必須先釋放其占有的 VIP。這個過程會產生一些異常問題:

故障轉移的順序,首先是請求故障機器釋放 VIP,然后聯系新的主庫機器分配 VIP。但是,如果故障機器本身不能訪問,或者說拒絕釋放 VIP 呢?考慮到機器故障的場景,故障機器不會立即響應或根本就不會響應釋放 VIP 的請求,整個過程有下面兩個問題:

腦裂情況:如果有兩個主機持有相同的 VIP 的情況,不同的客戶端根據最短的網絡鏈路將會連接到不同的主機上。

整個 VIP 重新分配過程依賴兩個獨立服務器的相互協調,而且設置過程是不可靠的。

即使故障機器正常釋放 VIP,整個流程也是非常耗時的,因為切換過程還需要連接故障機器。

即使 VIP 重新分配,客戶端已有的連接不會自動斷開舊的故障機器,從而使得整個系統產生腦裂的情況。

在我們實際設置 VIP 時,VIP 還受實際物理位置的約束。這主要取決于交換機或者路由器所在。因此,我們只能在同一本地服務器上重新分配 VIP。特別是在某些情況下,我們無法將 VIP 分配給其他數據中心的服務器,而必須進行 DNS 更改。

DNS 更改需要更長的時間傳播。客戶端緩存 DNS 名稱會先配置時間。跨平臺故障轉移意味著需要更多的中斷時間:客戶端需要花費更多時間去識別新的主服務器。

僅這些限制就足以推動我們尋找新的解決方案,但需要考慮的是:

主服務器使用 pt-heartbeat 服務去自注入訪問心跳,目的是延遲測量和節流控制。該服務必須在新的主服務器開始。如果可以,在更換主服務器的同時會關閉舊的主服務器這項服務。

同樣地,Pseudo-GTID 是由服務器自行管理的。它需要在新的主服務器開始,最好在舊的主服務器上停止。

新的主服務器將設置為可寫入。如果可以的話,舊的主服務器將設置為 read_only(只讀)。

這些額外的步驟是導致總停機時間的一個因素,并引入了它們自己的故障和摩擦。

解決方案是有效的,GitHub 已經成功地進行了 MySQL 故障轉移,但是我們希望 HA 在以下方面有所改進:

與數據中心無關。

容忍數據中心故障。

刪除不可靠的協作工作流。

減少總停機時間。

盡可能的,有無損的故障切換。

GitHub 的高可用解決方案:orchestrator,Consul,GLB

新策略可以改進,解決或者優化上面提到的問題。現在高可用的組成如下:

orchestrator 執行檢測和故障轉移。如鏈接中描述的那樣采用混合數據中心 orchestrator/raft。

Hashicorp 的 Consul 作為服務發現。

GLB/HAProxy 作為客戶端和寫入節點之間的代理。GLB 指導是開源的.

anycast 作為網絡路由。

新的結構移除了 VIP 和 DNS。在引入更多的組件的同時,我們能夠解藕這些組件,并且簡化相關的任務,并易于利用可靠穩定的解決方案。詳情如下。

正常過程

正常情況,應用通過 GLB/HAProxy 連接到寫入節點。

應用感知不到 master 身份。之前,都是使用名稱。例如 cluster1 的 master 是 mysql-writer-1.github.net。現在的結構中,這個名稱被  anycast IP 取代。

通過 anycast,名稱被相同的 IP 取代,但流量由客戶端的位置來進行路由。特別的,當數據中心有 GLB 時,高可用負載均衡器部署在不同的盒子內。通向 mysql-writer-1.github.net 的流量都被引流到本地的數據中心的 GLB 集群。這樣所有的客戶端都由本地代理服務。

在  HAProxy 頂層使用 GLB。HAProxy 擁有   寫入池:每個 MySQL 集群都有一個。每個池都有一個后端服務:集群 master 節點。數據中心的所有 GLB/HAProxy 盒子都有相同的池子,表示這些池子有相同的后端服務對應。所以如果應用期望寫  mysql-writer-1.github.net,不同關心連接哪個 GLB 服務。它會導向實際的 cluster1 master 節點。

就應用連接 GLB,發現服務而言,不需要重新發現。GLB 負責全部流量導向正確的目的地。

GLB 是怎么知道哪些服務是后端,以及如何告知 GLB 變化的呢?

Discovery via Consul

Consul 以服務發現解決方案而聞名,也提供 DNS 服務。然而,在我們的解決方案中,我們將其用作高度可用的鍵值 (KV) 存儲。

在 Consul 的 KV 存儲中,我們寫入集群主節點的身份。對于每個集群,都有一組 KV 條目指示集群的主設備 fqdn、端口、ipv4、ipv6。

每個 GLB/HAProxy 節點都運行 consul-template:一個監聽 Consul 數據變化的服務(在我們的例子中:集群主數據的變化)。consul-template 生成一個有效的配置文件,并且能夠在配置更改時重新加載 HAProxy。

因此,每個 GLB/HAProxy 機器都會觀察到 Consul 對 master 身份的更改,然后它會重新配置自己,將新的 master 設置為集群后端池中的單個實體,并重新加載以反映這些更改。

在 GitHub,我們在每個數據中心都有一個 Consul 設置,并且每個設置都是高度可用的。但是,這些設置彼此獨立。它們不會在彼此之間復制,也不會共享任何數據。

Consul 如何獲知變化,信息如何跨 DC 分發?

orchestrator/raft#

我們運行一個 orchestrator/raft 設置:orchestrator 節點通過 raft 機制相互通信。每個數據中心有一個或兩個 orchestrator 節點。

orchestrator 負責故障檢測和 MySQL 故障切換,以及將 master 的變更傳達給 Consul。故障切換由單個 orchestrator/raft leader 節點操作,但是集群現在擁有新 master 的消息通過 raft 機制傳播到所有 orchestrator 節點。

當 orchestrator 節點收到 master 變更的消息時,它們各自與本地 Consul 設置通信:它們各自調用 KV 寫入。具有多個 orchestrator 代理的 DC 將多次(相同)寫入 Consul。

把流程組合起來

在 master 崩潰的情況下:

orchestrator 節點檢測故障.

orchestrator/raft leader 節點開始恢復,一個數據服務器被更新為 master。

orchestrator/raft 公告所有 raft 子集群節點變更了 master。

每個 orchestrator/raft 成員收到一個 leader 節點 變更的通知。它們每個成員都把新的 master 更新到本地 Consul KV 存儲中。

每個 GLB/HAProxy 都運行了 consul-template,該模版觀察 Consul KV 存儲中的更改,并重新配置和重新加載 HAProxy。

客戶端流量被重定向到新的 master。

每個組件都有明確的責任歸屬,整個設計既是解耦的,又是簡化的。orchestrator 不知道負載平衡器。Consul 不需要知道消息的來源。代理只關心 Consul。客戶端只關心代理。

此外:

沒有更改要傳播的 DNS

沒有 TTL。

流沒有和故障的 master 合作,它很大程度被忽略了。

其他詳細信息

為了進一步保護流量,我們還有以下內容:

HAProxy 配置了一個非常短的 hard-stop-after。當它重新加載寫入器池中的新后端服務器時,它會自動終止與舊主服務器的任何現有連接。

使用 hard-stop-after,我們甚至不需要客戶的合作,這減輕了腦裂的情況。值得注意的是,這不是封閉的,并且在我們終止舊連接之前一段時間過去了。但是在某個時間點之后,我們會感到很舒服,并且不會期待任何令人討厭的驚喜。

我們并不嚴格要求 Consul 隨時待命。事實上,我們只需要它在故障轉移時可用。如果 Consul 發生故障,GLB 將繼續使用最后的已知值進行操作,并且不會采取劇烈行動。

GLB 設置為驗證新提升的 master 的身份。與我們的 上下文感知 MySQL 池 類似,會在后端服務器上進行檢查,以確認它確實是寫入器節點。如果我們碰巧在 Consul 中刪除了 master 的身份,沒問題;空條目被忽略。如果我們在 Consul 中錯誤地寫了一個非主服務器的名字,沒有問題;GLB 將拒絕更新它并繼續以最后一個已知狀態運行。

我們將在以下部分進一步解決問題并追求 HA 目標。

Orchestrator/RAFT 故障檢測 #

orchestrator 使用 整體方法 來檢測故障,因此非常可靠。我們沒有觀察到誤報:我們沒有過早的故障轉移,因此不會遭受不必要的停機時間。

orchestrator/raft 進一步解決了完整的 DC 網絡隔離(又名 DC 圍欄)的情況。DC 網絡隔離可能會導致混亂:該 DC 內的服務器可以相互通信。是它們與其他 DC 網絡隔離,還是其他 DC 被網絡隔離?

在 orchestrator/raft 設置中,raft 領導節點是運行故障轉移的節點。領導者是獲得組中大多數人(法定人數)支持的節點。我們的協調器節點部署是這樣的,沒有一個數據中心占多數,任何 n-1 數據中心都可以。

在 DC 網絡完全隔離的情況下,該 DC 中的 orchestrator 節點會與其他 DC 中的對等節點斷開連接。因此,孤立 DC 中的 orchestrator 節點不能成為 raft 集群的領導者。如果任何這樣的節點恰好是領導者,它就會下臺。將從任何其他 DC 中分配新的領導者。該領導者將得到所有其他能夠相互通信的 DC 的支持。

因此,發號施令的 orchestrator 節點將是網絡隔離數據中心之外的節點。如果一個獨立的 DC 中有一個主控,orchestrator 將啟動故障轉移,用其中一個可用 DC 中的服務器替換它。我們通過將決策委托給非隔離 DC 中的法定人數來緩解 DC 隔離。

更快的廣而告之

通過更快地公布主要更改可以進一步減少總停機時間。如何實現這一點?

當 orchestrator 開始故障轉移時,它觀察可用于提升的服務器隊列。理解復制規則并遵守提示和限制,它能夠對最佳操作過程做出有根據的決策。

它可能認識到,一個可用于促銷的服務器也是一個理想的候選人,例如:

沒有什么可以阻止服務器的升級 (用戶可能已經暗示這樣的服務器是首選的升級),以及

預計服務器能夠將其所有兄弟服務器作為副本。

在這種情況下,orchestrator 首先將服務器設置為可寫的,然后立即宣傳服務器的推廣 (在我們的例子里是寫到 Consul KV 存儲中),即使異步開始修復復制樹,這個操作通常需要幾秒鐘。

很可能在 GLB 服務器完全重新加載之前,復制樹已經完好無損,但是并不嚴格要求它。服務器很好接收寫!

半同步復制

在 MySQL 的半同步復制中,主服務器不會確認事務提交,直到已知更改已發送到一個或多個副本。它提供了一種實現無損故障轉移的方法:應用于主服務器的任何更改要么應用于主服務器,要么等待應用于其中一個副本。

一致性伴隨著成本:可用性的風險。如果沒有副本確認收到更改,主服務器將阻塞并停止寫操作。幸運的是,有一個超時配置,超時后主服務器可以恢復到異步復制模式,從而使寫操作再次可用。

我們已經將超時設置為一個合理的低值: 500ms。將更改從主 DC 副本發送到本地 DC 副本,通常也發送到遠程 DC,這已經足夠了。通過這個超時,我們可以觀察到完美的半同步行為 (沒有退回到異步復制),并且在確認失敗的情況下可以很輕松地使用非常短的阻塞周期。

我們在本地 DC 副本上啟用半同步,在主服務器死亡的情況下,我們期望 (盡管不嚴格執行) 無損故障轉移。完全直流故障的無損故障轉移是昂貴的,我們并不期望它。

在嘗試半同步超時的同時,我們還觀察到了一個對我們有利的行為:在主要失敗的情況下,我們能夠影響理想候選對象的身份。通過在指定的服務器上啟用半同步,并將它們標記為候選服務器,我們能夠通過影響故障的結果來減少總停機時間。在我們的實驗中,我們觀察到我們通常最終會得到理想的候選對象,從而快速地廣而告之。

注入心跳

我們沒有在升級 / 降級的主機上管理 pt-heart 服務的啟動 / 關閉,而是選擇在任何時候在任何地方運行它。這需要進行一些修補,以便使 pt-heart 能夠適應服務器來回更改 read_only(只讀狀態) 或完全崩潰的情況。

在我們當前的設置中,pt-heart 服務在主服務器和副本上運行。在主機上,它們生成心跳事件。在副本上,他們識別服務器是 read_only(只讀) 的,并定期重新檢查它們的狀態。一旦服務器被提升為主服務器,該服務器上的 pt-heart 就會將服務器標識為可寫的,并開始注入心跳事件。

orchestrator 所有權委托 #

我們進一步 orchestrator:

注入 Pseudo-GTID ,

將提升的 master 設置為可寫,清除其復制狀態,以及,

如果可能,將舊主服務器設置為 read_only。

在所有的新 master 的基礎上,這減少了摩擦。一個剛剛被提升的 master 顯然應該是有生命力,并且可以被接受的,否則我們不會提升它。因此,讓 orchestrator 直接講更改應用于提升的 msater 是有意義的。

orchestrator 所有權委托 #

我們進一步 orchestrator:

Pseudo-GTID 注入,

將提升的 master 設置為可寫,清除其復制狀態,以及,

如果可能,將舊的 master 設置為 read_only。

在所有的新 master 的基礎上,這減少了摩擦。一個剛剛被提升的 master 顯然應該是有活力,并且可以被接受的,否則我們不會提升它。因此,讓 orchestrator 將更改直接應用于提升的 msater 是有意義的。

限制和缺點

代理層使應用程序不知道主服務器的身份,但它也掩蓋了應用程序的主服務器的身份。所有主要看到的都是來自代理層的連接,我們會丟失關于連接的實際來源的信息。

隨著分布式系統的發展,我們仍然面臨著未處理的場景。

值得注意的是,在一個數據中心隔離場景中,假設主服務器位于隔離的 DC 中,該 DC 中的應用程序仍然能夠寫入主服務器。一旦網絡恢復,這可能導致狀態不一致。我們正在努力減輕這種分裂的大腦實施一個可靠的 STONITH 從內部非常孤立的 DC。和以前一樣,在摧毀初選之前還需要一段時間,而且可能會有一段短時間的腦分裂。避免大腦分裂的操作成本非常高。

還存在更多的情況:在故障轉移時停止領事服務;部分直流隔離;其他情況。我們知道這種性質的分布式系統不可能堵住所有的漏洞,所以我們把重點放在最重要的案例上。

結論

我們的協調器 / GLB/Consul 為我們提供了:

可靠的故障檢測,

與數據中心無關的故障轉移,

通常無損的故障轉移,

數據中心網絡隔離支持,

緩解裂腦 (更多工作成果),

不依賴合作,

在大多數情況下,總中斷時間在 10 and 13 seconds 之間。

在不常見的情況下,我們最多可以看到 20 seconds 的總停機時間,在極端情況下則可以看到最多 25 seconds 的停機時間。

關于“GitHub 如何做好 MySQL 高可用性”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“GitHub 如何做好 MySQL 高可用性”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-13發表,共計7393字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 波密县| 鸡西市| 称多县| 合川市| 遵化市| 五台县| 侯马市| 灵台县| 道孚县| 津市市| 光山县| 彰武县| 伊宁县| 英山县| 棋牌| 合山市| 通州区| 沈丘县| 南木林县| 德惠市| 景德镇市| 长白| 金坛市| 南安市| 台中市| 成安县| 子洲县| 阿勒泰市| 和平区| 读书| 特克斯县| 安阳市| 商水县| 台州市| 安庆市| 集安市| 泽普县| 惠来县| 磐安县| 六枝特区| 光山县|