歡迎光臨
每天分享高質量文章

一篇文章讀懂分佈式通信協議

最近一年左右在研究系統架構和分佈式系統,今天跟大家一起分享討論。文章簡單分享幾種分佈式系統的一致性演算法,常見的有 Paxos、Raft、ZAB。
分佈式系統

首先簡單說一下分佈式系統。這是一個比較寬泛的概念。他的產生和出現是為了應對和解決以往系統的問題。
我的簡單理解是一套互相連接共同向外提供服務的系統,系統內部節點間通過某種方式進行通信。常見的大的如電商網站,小的如一個資料庫集群,快取集群等。 
在分佈式系統出現之前使用的單機系統,一旦服務器的操作系統、硬碟、網絡等出現問題,就可能會出現服務中斷,資料丟失等問題。 另外,單機的性能再高,儲存能力再擴展,也是有限的,而分佈式系統可以包含大量的服務器用來分散帶寬、儲存和計算壓力。 第三,由於跨較遠區域甚至跨國的網絡延遲有時還是客觀的,所以服務器集中在一個地方很難向較大範圍提供較好的服務和體驗。
百度上對分佈式系統的解釋:
  • 分佈式系統(distributed system)是建立在網絡之上的軟體系統。正是因為軟體的特性,所以分佈式系統具有高度的內聚性和透明性。

個人對這裡的內聚性和透明性的理解是:
  • 內聚性:系統內的節點、服務目的、分工、規則明確。

  • 透明性:分佈式系統對外提供服務,呼叫該系統的外部用戶不用考慮塔式怎麼工作的,只要根據規則進行使用就成,也不需要知道裡面包含多少台計算機,都在什麼地方。

同時由於不完美的運行環境,他本身需要解決一些問題。
如:系統中使用的每個節點都可能出現單點故障突然不工作了,節點間會有或大或小、忽大忽小的網絡延遲,節點間的網絡也有可能出問題。 從技術角度看,可能發生的問題基本上認為早晚會發生。說到底很多問題就是概率和成本收益的平衡。 因此,一個分佈式系統要正常提供對外的服務,它的設計本身就要考慮到這些問題的解決。 在演算法層面就是由分佈式系統的一致性演算法來輔助解決和應對這些問題,確保系統盡可能的對外正常的提供服務。
這裡說盡可能的意思是分佈式系統不能確保永遠完全沒有問題,尤其是一些極端情況。 比如一個3個節點的資料庫集群,單節點掛掉的概率較小,3個節點同時掛掉的概率極小極小,不過也存在這種可能,不過概率很小,一般不考慮。 或者機房停電,光纜被挖段,如果幾個節點都在一個機房,那就不能工作了。 今天講的一致性演算法主要解決的是從系統的角度分析一個分佈式系統內部節點本身和節點間出現問題的解決。 跟這些外部問題關聯較小,那些場景要同時借助其他手段來緩解和解決。


一致性問題

比較容易理解的常見的實際問題: 一個系統包含5個節點,由於網絡原因其中3個節點和另2個節點失去了聯繫,這時候系統應該怎麼處理,是否還可以繼續提供服務。
如果繼續提供服務,他們之間的資料就是不一致的,後面節點間的網絡恢復後,怎麼解決資料不一致的問題。 
節點間的網絡延遲、磁盤讀寫、CPU處理能力不同,儲存到這個系統中的資料在哪些情況下可以認為儲存成功了,還要以一種效率較高的方式來實現。


三、ZAB協議

ZAB的基本特點
把節點分兩種,Leader(主)和Follower(從)。 有一個主節點,所有寫操作全部通過節點進行處理,如果一個從節點收到了一個寫操作請求,就會轉給主節點處理。 其他節點都是從節點,可以通過從節點進行讀操作。 主節點通過選舉得出,主節點失蹤後,其他從節點自動開始選舉新的主節點。
註意, 這裡寫操作可以認為是儲存或修改現有資料。讀操作可以認為是讀一個現存的資料出來。讀操作相對簡單一些,這裡主要講寫操作, 其流程為:
  1. 客戶向主節點請求寫資料X;

  2. 主節點為該資料生成一個唯一的遞增Id,叫ZXIDX(Id);

  3. 主節點把X(Id)發給所有的從節點,跟他們確認能不能正常把資料記錄下來,這個操作叫 Propose 提議;

  4. 超過一半的節點向主節點回覆沒問題,這個回覆操作叫 ACK 應答;

  5. 節點收到一半以上從節點的肯定答覆後,給所有的從節點發送確認提交請求,表示你們可以把這個資料儲存下來了,同時自己也正式儲存這個資料,這個過程叫 Commit 提交。

現在問題來了,如果沒有超過一半的從節點給主節點回覆ACK。那麼主節點就不能確認該訊息可以成功記錄下來。 為啥一定要收到超過一半的從節點的答覆?答案是為了確保資料的一致性。 一般分佈式一致性演算法可以確保在部分節點掛掉的情況下保持資料的一致性,在大部分節點都同時掛掉的情況不能確保。比如:一共5個節點,2個掛掉沒問題,其中可以包括主節點,如果3個掛掉了,就不能確保了。 一般出現這種情況時,比如5個節點只剩了2個,這兩個節點就不再提供服務了。
工作流程
比如一個銀行的存款系統:3個節點在上海,2個節點在廣州。一個賬號Adun,有1K的錢在裡面。5個節點都包含這個資料。 這時上海廣州之間的網絡掛了。我連到上海的節點把錢轉給一個人,然後連到廣州的節點把裡面的1K錢轉給另一個人。 他們之間是斷開的,如果同時提供轉賬服務,就出現了資料一致性的問題。 而如果只有3個節點的上海提供服務就沒有這個問題了。 另一個問題是,他們之間的網絡恢復後,以誰的資料為準呢?所以大部分的分佈式一致性演算法都是採用大多數認同的方式。 當然,在寫資料的時候如果強制確認所有節點都寫入了新資料會更安全和一致,但是系統的可用性和性能就大大降低了,只要有一個節點掛了,系統就不工作了。
我們分析下子節點掛掉的情況。 先看節點掛掉數占比情況分析: 少於一半的子節點掛掉沒有任何影響。達到一半的子節點掛掉系統不能提供服務,一般這種情況概率很小。
一個子節點掛掉一段時間後又恢復了之後, 先通過主節點同步新的資料,因為自己掛了一段時間,很可能沒有最新的資料。資料同步之後正式成為工作的子節點開始工作。 添加一個新的子節點到一個現有的集群,也是這個過程。
如果是主節點掛掉,情況會複雜一點。 主節點掛掉後,集群暫時不提供寫服務,開始新的主節點選舉。選舉規則如下:
  1. 發訊息到每一個自己還能連上的節點:包含自己的節點編號叫 myid 和 自己儲存的資料的最大的 ZXID。

  2. 誰的ZXID最大,誰就是新的主節點。為什麼吶?因為這表示他的資料最新。儘量確保資料一致性。

  3. ZXID相同的時候,誰的myid最大誰是新的主節點;

  4. 收到其他節點的資料後,跟自己的判斷,如果對方比自己的大,就認同對方為主節點;

  5. 得到一半以上(註意這裡又是一半以上),節點認同的候選的節點成為新的主節點。

新的主節點選舉出來之後,進入集群的資料同步節點,先檢查集群內部哪些節點的資料比自己舊,把資料同步過去。 然後開始向外部提供服務。 在新的主節點選出來之前,集群不能提供寫服務。 這裡的步驟有好幾步,在正常的服務器環境下,這個過程是很快的,幾十到幾百毫秒。
回到剛纔的上海和廣州的場景。 廣州的發現上海的節點失蹤了,這時候開始選舉新的主節點,但是它們只有2個節點,選不出來主節點,也不提供服務。上海的繼續服務。網絡恢復後,把資料同步到廣州節點然後繼續工作。
這是 ZAB 協議的主要信息。還有很多細節,感興趣的話可以去看看。不過一般分佈式系統的一致性演算法都有點複雜。ZAB是為了支撐ZooKeeper服務設計出來的,ZooKeeper是給其他服務提供集群管理服務的,所以他本身要足夠健壯。ZAB協議的全稱就是Zookeeper Atomic Broadcast,即 ZooKeeper原子性廣播協議。
Raft 演算法

下麵再簡單介紹幾句Raft演算法。 Raft演算法很多地方跟ZAB很像,也分主節點和從節點,主節點選舉的地方有一點差別。
  1. 發現主節點失蹤一段時間後,所有從節點向其他從節點發訊息,讓他們選自己為新的主節點;

  2. 還沒參加選舉的節點如果收到其他節點的選舉請求,就選舉自己收到的第一個節點,後面誰再請求自己支持選舉,就告訴他們我已經支持另一個節點了;

  3. 如果一個節點發現另一個節點得到的支持比自己多,也就開始無條件支持那個節點選舉,同時讓支持自己的節點也去支持它

  4. 如果一輪沒選出來得到大多數節點支持的主節點,就開始下一輪選舉,直到一個節點得到了大部分節點支持,成為新的主節點。

Paxos 演算法

還有一個叫Paxos的一致性演算法,更複雜,慚愧我目前還不敢確保完全理解,Paxos演算法還衍生出來好幾種變體,經典的Paxos演算法不分主節點和從節點。 
其實現在大部分的一致性演算法都是起源於或參考了Paxos演算法,有人說只有Paxos才是真正的一致性演算法。


Q&A;

Q:主節點本身也是選舉出來的,如果主節點掛了呢?
A:一般分佈式一致性演算法可以確保在部分節點掛掉的情況下保持資料的一致性,在大部分節點都同時掛掉的情況不能確保。比如一共5個節點,2個掛掉沒問題,其中可以包括主節點,如果3個掛掉了,就不能確保了。一般出現這種情況時,比如5個節點只剩了2個,這兩個節點就不再提供服務了。
Q:在主節點失去心跳到選舉新的主節點作為寫入,這期間的資料怎麼保證最終一致?那還是這個問題。
A:主節點失聯的時候不能寫資料。如果此時主節點上有沒有提交的資料它就掛了,那麼客戶端就不能得到這個訊息成功寫入的響應。因此系統本身的資料是一致的。主節點上沒提交的資料在從節點上也是未提交,因此沒提交資料的ZXID不算數。嚴格的講這段時間系統是不可寫的。
Q:一般主從節點重新選舉的頻率是多少?
A:這個要看具體情況了,跟服務器,網絡,機房環境,系統本身開發的怎麼樣,壓力這些都有關係;節點掛掉才會進行選舉,不過具有主節點的系統,主節點的壓力也會比較大,協議的具體實現互相差別也很大,涉及到開發細節的話還有很多引數要考慮,比如心跳間隔,節點數量等。
本文轉載自公眾號: 鳳凰牌老熊,點擊查看原文

Kubernetes實戰培訓

Kubernetes應用實戰培訓將於2018年10月12日在深圳開課,3天時間帶你系統學習Kubernetes本次培訓包括:容器基礎、Docker基礎、Docker進階、Kubernetes架構及部署、Kubernetes常用物件、Kubernetes網絡、儲存、服務發現、Kubernetes的調度和服務質量保證、監控和日誌、Helm、專案實踐等,點擊下方圖片查看詳情。

赞(0)

分享創造快樂