分佈式設計與開發中有些疑難問題必須藉助一些算法才能解決,好比分佈式環境一致性問題,感受如下分佈式算法是必須瞭解的(隨着學習深刻有待添加):html
Paxos算法ios
一致性Hash算法算法
Paxos算法apache
1)問題描述
網絡
分佈式中有這麼一個疑難問題,客戶端向一個分佈式集羣的服務端發出一系列更新數據的消息,因爲分佈式集羣中的各個服務端節點是互爲同步數據的,因此運行完客戶端這系列消息指令後各服務端節點的數據應該是一致的,但因爲網絡或其餘緣由,各個服務端節點接收到消息的序列可能不一致,最後致使各節點的數據不一致。舉一個實例來講明這個問題,下面是客戶端與服務端的結構圖:框架
當client一、client二、client3分別發出消息指令A、B、C時,Server1~4因爲網絡問題,接收到的消息序列就可能各不相同,這樣就可能因爲消息序列的不一樣致使Server1~4上的數據不一致。對於這麼一個問題,在分佈式環境中很難經過像單機裏處理同步問題那麼簡單,而Paxos算法就是一種處理相似於以上數據不一致問題的方案。分佈式
2)算法自己工具
算法自己我就不進行完整的描述和推導,網上有大量的資料作了這個事情,但我學習之後感受萊斯利·蘭伯特(Leslie Lamport,paxos算法的奠定人,此人如今在微軟研究院)的Paxos Made Simple 是學習paxos最好的文檔,它並無像大多數算法文檔那樣搞一堆公式和數學符號在那裏嚇唬人,而是用人類語言讓你搞清楚Paxos要解決什麼問題,是如何解決的。這裏也藉機抨擊一下那些學院派的研究者,要想讓別人承認你的成果,首先要學會怎樣讓大多數人樂於閱讀你的成果,而這個描述Paxos算法的文檔就是咱們學習的榜樣。oop
言歸正傳,透過Paxos算法的各個步驟和約束,其實它就是一個分佈式的選舉算法,其目的就是要在一堆消息中經過選舉,使得消息的接收者或者執行者能達成一致,按照一致的消息順序來執行。其實,以最簡單的想法來看,爲了達到大夥執行相同序列的指令,徹底能夠經過串行來作,好比在分佈式環境前加上一個FIFO隊列來接收全部指令,而後全部服務節點按照隊列裏的順序來執行。這個方法固然能夠解決一致性問題,但它不符合分佈式特性,若是這個隊列down掉或是不堪重負這麼辦?而Paxos的高明之處就在於容許各個client互不影響地向服務端發指令,大夥按照選舉的方式達成一致,這種方式具備分佈式特性,容錯性更好。學習
說到這個選舉算法自己,能夠聯想一下現實社會中的選舉,通常說來都是得票者最多者獲勝,而Paxos算法是序列號更高者獲勝,而且當嘗試提交指令者被拒絕時(說明它的指令所佔有的序列號不是最高),它會從新以一個更好的序列參與再次選舉,經過各個提交者不斷參與選舉的方式,達到選出大夥公認的一個序列的目的。也正是由於有這個不斷參與選舉的過程,因此Paxos規定了三種角色(proposer,acceptor,和 learner)和兩個階段(accept和learn),三種角色的具體職責和兩個階段的具體過程就見Paxos Made Simple ,另一個國內的哥們寫了個不錯的PPT ,還經過動畫描述了paxos運行的過程。不過仍是那句話不要一開始就陷入算法的細節中,必定要多想一想設計這些遊戲規則的初衷是什麼。
Paxos算法的最大優勢在於它的限制比較少,它容許各個角色在各個階段的失敗和重複執行,這也是分佈式環境下常有的事情,只要大夥按照規矩辦事便可,算法的自己保障了在錯誤發生時仍然獲得一致的結果。
3)算法的實現
Paxos的實現有不少版本,最有名的就是google chubby ,不過看不了源碼。開源的實現可見libpaxos 。另外,ZooKeeper 也基於paxos解決數據一致性問題,也能夠看看它是若是實現paxos的。
4)適用場景
弄清楚paxos的前因後果後,會發現它的適用場景很是多,Tim有篇blog《Paxos在大型系統中常見的應用場景》 專門談這個問題。我所見到的項目裏,naming service是運用Paxos最廣的領域,具體應用可參考ZooKeeper
一致性Hash算法
1)問題描述
分佈式經常用Hash算法來分佈數據,當數據節點不變化時是很是好的,但當數據節點有增長或減小時,因爲須要調整Hash算法裏的模,致使全部數據得從新按照新的模分佈到各個節點中去。若是數據量龐大,這樣的工做經常是很難完成的。一致性Hash算法是基於Hash算法的優化,經過一些映射規則解決以上問題
2)算法自己
對於一致性Hash算法自己我也不作完整的闡述,有篇blog《一致性hash算法 - consistent hashing》 描述這個算法很是到位,我就不重複造輪子了。
實際上,在其餘設計和開發領域咱們也能夠借鑑一致性Hash的思路,當一個映射或規則致使有難以維護的問題時,能夠考慮更一步抽象這些映射或規則,經過規則的變化使得最終數據的不變。一致性hash實際就是把之前點映射改成區段映射,使得數據節點變動後其餘數據節點變更儘量小。這個思路在操做系統對於存儲問題上體現不少,好比操做系統爲了更優化地利用存儲空間,區分了段、頁等不一樣緯度,加了不少映射規則,目的就是要經過靈活的規則避免物理變更的代價
3)算法實現
一致性Hash算法自己比較簡單,不過能夠根據實際狀況有不少改進的版本,其目的無非是兩點:
節點變更後其餘節點受影響儘量小
節點變更後數據從新分配儘量均衡
實現這個算法就技術自己來講沒多少難度和工做量,須要作的是創建起你所設計的映射關係,無需藉助什麼框架或工具,sourceforge上卻是有個項目libconhash ,能夠參考一下
以上兩個算法在我看來就算從不涉及算法的開發人員也須要了解的,算法其實就是一個策略,而在分佈式環境經常須要咱們設計一個策略來解決不少沒法經過單純的技術搞定的難題,學習這些算法能夠提供咱們一些思路。