1. 程式人生 > >架構應用之高可用、高複用

架構應用之高可用、高複用

架構應用之高可用、高複用

架構應用之高可用、高複用

 

一、儲存高可用

儲存的高可用,主要是通過資料冗餘的方式來實現高可用,複雜性主要是在如何保持資料一致性,複製延遲和網路中斷都會帶來資料不一致。主要考慮的就是,資料如何複製,如何應對複製延遲,如何應對複製中斷,各個節點的職責是什麼。

常見的儲存架構:主從,主備,主主,叢集,分割槽。

1.主備,最常見最簡單的一種儲存方案。

主機儲存資料,通過複製通道將資料複製到備機,客戶端無論讀寫操作 ,都發送給主機。

備機不對外提供任何讀寫服務。

主機故障情況下,此時整個系統處於不可用狀態,不能讀寫資料,如果主機不能恢復(例如,機器硬碟損壞,短時間內無法恢復), 則需要人工操作, 將備機升為主機。

優點:

對於客戶端來說,不需要感知備機的存在。即使災難恢復後,客戶端無須知道是原來的備機升級為主機了 。

對於主機和備機來說 , 雙方只需要進行資料複製即可,無須考慮太複雜的資料一致性問題。

缺點:

備機僅僅只為備份,並沒有提供讀寫操作 ,硬體成本上有浪費。

故障後需要人工干預,無法自動恢復。

綜合主備複製架構的優缺點,內部的後臺管理系統使用主備複製架構的情況會比較多,資料變更頻率很低,即使在某些場景下丟失,也可以通過人工的方式補全。

2.主從,主機負責讀寫操作,從機只負責讀操作,不負責寫操作。

主機儲存資料,通過複製通道將資料複製到從機。

正常情況下,客戶端寫操作傳送給主機,讀操作可傳送給主機也可以傳送給從機。

主機故障情況下,客戶端無法進行寫操作,但可以將讀操作傳送 給從機,從機繼續響應讀操作。如果主機不能恢復(例如,機器硬碟損壞,短時間內無法恢復), 則需要人工操作, 將備機升為主機。

如果主從間資料複製延遲,則會出現主從讀取的資料不一致的問題。

主從複製與主備複製相比,有以下不同的優缺點 :

主從複製在主機故障時,讀操作相關的業務不受影響;發揮了硬體的效能;

主從複製要比主備複製複雜更多,主要體現在客戶端需要感知主從關係,並將不同的操作發給不同的機器進行處理 。

綜合主從複製的優缺點 , 一般情況下,寫少讀多的業務使用主從複製的儲存架構比較多。例如,論壇、 BBS 、新聞網站這類業務。

主備倒換與主從倒換:

主機故障後,無法進行寫操作 ,需要人工指定新的主機角色。

主備倒換和主從倒換方案就是為了解決上述問題而產生的。簡單來說,這兩個方案就是在原有方案的基礎上增加 “倒換”功能, 即系統自動決定主機角色, 並完成角色切換 。

倒換方案的實現的要點:

主備間狀態判斷,狀態傳遞的渠道(相互連線,還是第三方仲裁),狀態檢測的內容(程序存在,響應緩慢等)

倒換決策,什麼情況下備機升級為主機,原來主機恢復後是否要再次倒換,倒換是完全自動,還是半自動需要人工確認。

資料衝突解決,原故障主機恢復後,新舊主機之間可能存在資料衝突。

3.主主複製,兩臺主機都儲存資料,客戶端將讀寫操作傳送給任意一臺主機。

主主複製架構,必須保證資料能夠雙向複製,對資料的設計有嚴格的要求,一般適合於那些臨時性,可丟失,可覆蓋的資料場景。例如使用者的session資料,使用者的行為日誌資料,論壇的草稿資料等。

4.資料叢集,這裡主要指資料分散叢集,每臺伺服器負責儲存一部分資料,同時每臺伺服器會備份一部分資料。

設計叢集時考慮點:

均衡性,保證伺服器上的資料分割槽基本是均衡的。

容錯性,當部分伺服器故障時,將原來分配給故障伺服器的資料分割槽分配給其他伺服器。

可伸縮性,當叢集容量不夠,擴充新伺服器後,能夠自動將部分資料分割槽遷移至新伺服器,保證擴容後的均衡性。

資料分散叢集中的每臺伺服器都可以處理讀寫請求,必須有一個角色來負責執行資料分配演算法,就像hadoop中的namecode。

分散式事務

資料可能分佈在不同的叢集節點上,由於節點間只能通過訊息進行通訊,因此分散式事務只能依賴訊息通知,訊息的不可靠性,這就帶來了分散式事務的複雜性。

分散式事務演算法中常見的有“二階段提交”和“三階段提交”

二階段提交,“commit請求階段”和“commit提交階段”,(1)存在一個節點協調者,協調者向所有參與者傳送詢問是否可以執行提交事務;(2)參與者執行事務操作,執行成功,則將undo資訊和redo資訊寫入日誌,鎖定資源返回YES不提交事務,執行失敗,返回NO給協調者;(3)協調者收到響應訊息都為YES時,傳送COMMIT請求,如果任一參與者返回NO,則傳送ROLLBACK請求,參與者執行事務操作,返回ACK訊息,協調者收到反饋後確認是完成或取消事務。

實現簡單,但缺點也很明顯:同步阻塞,協調者和參與者互相等待響應訊息,如果某個節點響應訊息比較慢,則整個系統全部被拖慢,不適合高併發場景;狀態不一致,某一參與者如果沒有收到commit訊息,會一直等待直到超時後回滾事務,其他參與者都已提交事務,導致事務狀態不一致。

三階段提交,協調者先向所有參與者傳送一個詢問是否可以執行事務,協調者在超時時間內收到所有yes後進入第二階段;協調者傳送準備提交請求,參與者執行事務操作,記錄undo和redo事務日誌,返回ACK訊息;協調者收到所有ACK訊息後,傳送commit請求,如果沒有收到全部ACK,則會發出回滾請求,參與者收到請求執行操作,如果等待超時還是會執行commit請求。

5.資料分割槽,指將資料按照一定的規則進行分割槽,不同分割槽分佈在不同的地理位置上。

通過這種方式來規避地理級別的故障造成的巨大影響。

常見的分割槽複製規則:(1)集中式,備份指存在一個總的備份中心,所有的分割槽都將資料備份到備份中心。設計簡單,分割槽間無互動,擴充套件容易,成本較高。(2)互備式,每個分割槽備份另外一個分割槽的資料,設計複雜,分割槽相互間互相關聯和影響,擴充套件複雜,成本低,直接利用已有的裝置。(3)獨立式,每個分割槽自己有獨立的備份中心,設計簡單,擴充套件容易,成本高。

二、計算高可用

當部分硬體損壞時,計算任務能夠繼續正常執行。通過增加更多服務來達到計算高可用。

主備架構是計算高可用最簡單的架構,可以細分為冷備架構和福備架構,常用溫備架構 。

溫備架構,備機上的業務系統己經啟動,只是不對外提供服務,主機故障後,人工只需要將任務分 配器的任務請求切換為傳送到備機即可。

高可用計算的叢集

對稱叢集,叢集中每個伺服器的角色都是一樣的,都可以執行所有任務,更通俗的叫法是負載均衡叢集。

非對稱叢集, 叢集中的 伺服器分為多個不同的角色,不同的角色執行不同的任務,例如,最常見的 Master-Slave 角色。

不同角色的伺服器承擔不同的職責 。 以 Master-Slave 為例,部分任務是 Master 伺服器才能執行,部分任務是 Slave 伺服器才能執行。當指定型別的伺服器故障時,需要重新分配角色。例如 ,Master 伺服器故障後, 需要將剩餘的 Slave 伺服器中的一個重新指定為 Master伺服器;Slave伺服器故障,只需要剔除就可以了。

以 ZooKeeper 為例:

( 1 )任務分配器: ZooKeeper 中不存在獨立的任務分配器節點,每個 Server 都是任務分配器, Follower 收到請求後會進行判斷,如果是寫請求就轉發給 Leader,如果是讀請求就自己處理。

(2 )角色指定: ZooKeeper 通過 ZAB 協議來選舉 Leader,當 Leader 故障後,所有的 Follower 節點會暫停讀寫操作,開始進行選舉,直到新的 Leader 選舉出來後才繼續對 Client 提供服務 。

三、業務高可用

業務高可用,如果保證了儲存高可用和計算高可用,業務高可用的保障也已經很高了,通常來說已經可以滿足大部分系統的需求了。這裡再談一下異地多活,針對極端情況的高可用方案。還有介面級故障方案,系統沒有宕機網路也沒問題情況下,表現為響應慢。

1.異地多活

異地就是指地理位置上不同的地方 通常指不同的機房, 類似於“不要把雞蛋都放在同一籃子裡”;

多活就是指不同地理位置上的系統都能夠提供業務服務。

實現異地多活有很高的代價,具體表現為:

• 系統複雜度會發生質的變化,需要設計複雜的異地多活架構。

• 成本會上升,畢竟要多在一個或多個機房搭建獨立的一套業務系統。

異地多活通常可以分為三種,同城異區,跨城異地,跨國異地。

同城異區指的是將業務部署在同一個城市不同區的多個機房 。關鍵在於搭建高速網路將兩個機房連線起來,達到近似一個本地機房的效果。架構設計 上可以將兩個機房當作本地機房來設計,無須額外考慮 。

跨城異地指的是業務部署在不同城市的多個機房,而且距離最好要遠一些。跨城異地距離較遠帶來的網路傳輸延遲問題,給業務多活架構設計帶來了複雜性,在資料短時間不一致的情況下,還能夠正常提供業務 。架構設計的主要目的就是為了解決這個矛盾。

跨城異地肯定會導致資料不一致,如何解決這個問題呢?

重點還是在“資料”上,即根據資料的特性來做不同的架構。如果 是強一致性要求的資料,例如,銀行存款餘額,支付寶餘額等,這類資料實際上是無法做到跨 城異地多活的 。

支付寶等金融相關的系統,對餘額這類資料,不能做跨 城異地的多活架構,而只能採用同城異區這種架構 。

跨國異地指的是業務部署在不同國家的多個機房。跨國異地的距離更加遠 了,因此資料同步的延時會更長,正常情況下可能就有幾秒鐘了。主要是面向不同地區使用者提供業務,或者提供只讀業務,對架構設計要求不高。

跨城異地多 活架構設計的一些技巧和步驟 :

技巧:

(1)保證核心業務的異地多活

(2)核心資料最終一致性,資料同步是異地多活架構的設計核心 。儘量減少資料同步,只同步核心業務相關的資料,保證最終一致性,不保證實時一致性。

採用多種手段同步資料:

儲存系統本身都會有同步的功能,MySQL 的主備複製、 Redis 的 Cluster 功能、 Elasticsearch 的叢集功能 。

當我們只考慮存 儲系統本身的同步功能時,就會發現無法做到真正的異地多活。以 MySQL 為例, MySQL5.l 版本的複製是單執行緒的複製,在網路抖動或大量資料 同步時 , 經常發生延遲較長的問題,短則延遲十幾秒,長則可能達到十幾分鍾 。

解決的方案就是拓展思路,避免只使用儲存系統的同步功能,可以將多種手段配合儲存系 統的同步來使用:1.訊息佇列方式,將資料通過訊息佇列同步到其他業務中心。2.二次讀取方式,B 中心在讀取本地資料失敗時,可以根據路由規則,再去 A 中心訪問一次。3.儲存系統同步方式。4.回源讀取方式,不同步資料,根據路由回原中心讀取。5.重新生成資料方式。

步驟:

第一步:業務分級,挑選出核心的業務,只為核心業務設計異地多活,降低方案複雜度和成本。

第二步:資料分類,識別所有的資料及資料特徵,資料特徵會影響後面的方案設計。

資料特徵分析維度:

資料量、唯一性(同類資料必須保證唯一 ,例如使用者 ID)、可丟失性、可恢復性

第三步 : 資料同步,根據不同的資料設計不同的同步方案。

第四步:異常處理,一旦出現極端異常的情況,總是會有部分資料出現異常的。出現這些問題時,系統將採 取什麼措施來應對。

常見的異常處理措施有如下幾類。

( 1 )多通道同步 。採取多種方式來進行資料同步,其中某條通道故障的情況下 ,系統可以通過其他方式來進行同步。

( 2 )同步和訪問結合。訪問指異地機房通過系統的介面來進行資料訪問 。

( 3 )日誌記錄 。用於故障恢復後對資料進行恢復。

2.介面級故障應對方案——降級、熔斷、限流、排隊

介面級故障的典型表現就是系統並沒有宕機, 網路也沒有中斷, 但業務卻出現問題了 。 例如,業務響應緩慢, 大量訪問超時, 大量訪問出現異常 ( 給使用者彈出提示“無法連線資料庫勺, 這類問題的主要原因在於系統壓力太大, 負載太高, 導致無法快速處理業務請求, 由此引發更多的後續問題。終端使用者看到的現象就是訪問很慢。

導致介面級故障的原因,一般有如下幾種 :

• 內部原因 程式 bug 導致死迴圈, 某個介面導致資料庫慢查詢, 程式邏輯不完善導致耗盡記憶體等。

• 外部原因 黑客攻擊、促銷或搶購引入了超出平時幾倍甚至幾十倍的使用者訪問, 第三方系統大量請求,第三系統響應緩慢, 等等 。

解決介面級故障的核心思想和異地多活基本類似:優先保證核心業務 , 優先保證絕大部分使用者 。

(1)降級,系統將某些業務或介面的功能降低,可以是隻提供部分功能,優先保證核心業務。

常見的實現降級 的方式有如下幾種 :

• 系統後門降級,系統預留了後門用於降級操作,系統提供一個降級 URL, 當訪問這個URL時 ,就相當於執行降級指令。

• 獨立降級系統,將降級操作獨立到一個單獨的系統中。

(2)熔斷,降級的目的是應對系統自身的故障,而熔斷的目的是應對依賴的外部系統故障的情況。

A 服務的 X 功能依賴 B 服務的某個介面,當 B 服務的介面響應很慢的時候, A 服務的 X 功能響應肯定也會被拖慢,進一步導致 A 服務的執行緒都被卡在 X 功能處 理上,此時 A 服務的其他功能都會被卡住或響應非常慢 。 這時就需要熔斷機制了,即 A 服務不 再請求 B 服務的這個介面, A 服務內部只要發現請求 B 服務的這個介面就立即返回錯誤,從而 避免 A 服務整個被拖慢甚至拖死。

熔斷機制實現的關鍵是需要有一個統一的 API 呼叫層,由 API 呼叫層來進行取樣或統計, 如果介面呼叫散落在程式碼各處就沒法進行統一處理了 。

另外一個關鍵是闊值的設計。1 分鐘內 30% 的請求響應時間超過 l 秒就熔斷,這個策略中的“ 1 分鐘”“ 30% ”“ l 秒”都對最終的熔斷效果有影響 。

(3)限流,限流則是從使用者訪問壓力的角度來考慮如何應對故障。 限流指只允許系統能夠承受的訪問量進來,超出系統訪問能力的請求將被丟棄。

限流一般都是系統內實現的 ,常見的限流方式可以分為兩類:基於請求限流和基於資源限流。

基於請求限流指從外部訪問的請求角度考慮限流,常見的方式有限制總量和限制時間量 。

基於資源限流是從系統內部考慮 的, 即找到系統內部影響效能的關鍵資源,對其使用上限進行限制 。 常見的內部資源有連線數、檔案控制代碼 、 執行緒 數、請求佇列等 。

(4)排隊,排隊實際上是限流的一個變種 ,限流是直接拒絕用 戶 ,排隊是讓使用者等待很長時間,

一般情況下, 排隊需要用獨立的系統去實現。例如,使用 Kafka 這類訊息佇列來快取使用者請求。