寫在前面
本系列博文為博主在學習《高階分散式系統》這門課的過程中寫就。目的有二,第一是記錄自己學習分散式系統的過程和心得,為後續從事分散式系統或者平行計算相關的研究打下較為夯實的基礎。第二則是鍛鍊自己的邏輯與寫作。本系列博文的寫作目標不是教科書式一板一眼的教學,而是一種介紹和導引。主要參考的寫作應當是牛津大學出版社的“牛津通識讀本”系列或者吳軍博士所著的《數學之美》與《浪潮之巔》等。
本系列博文主要包括以下內容:
- 課堂內容筆記的整理(Lecture Notes)
- 論文精讀(Paper Review)
- 作業記錄(Homework)
- 課程專案的構思和實現(Course Project)
如果要評選世界上分散式系統建設的最好的公司,那麼谷歌公司一定榜上有名。谷歌公司的業務遍佈全球,其搜尋服務能夠為世界上任何一處使用它的使用者提供相似的體驗,並且底層提供計算能力的機器也不是現今最先進的超級計算機,這都要歸功於谷歌建立的規模龐大的分散式基礎設施。圖1是一個非常簡化的谷歌的技術分層架構,在使用者直接使用的各種谷歌服務和底層提供計算能力的計算平臺之間,有著一個不可忽視的分散式系統基礎設施。
谷歌的Map/Reduce執行流程
從使用者的視角來看,使用谷歌的搜尋服務只需要在谷歌搜尋主頁的搜尋框中輸入搜尋關鍵詞,然後經過幾毫秒到幾百毫秒不等的時間,便可以獲得搜尋的結果。然而,表面上看似簡單快速的搜尋過程,在谷歌的伺服器中執行的過程可一點都不簡單,這背後的一整套流程由被稱作Map Reduce的技術來支援。從概念上來說,在分散式系統的層面,使用者的查詢程序(就是瀏覽器)會向三個部分的分散式節點fork這個查詢請求(如果不瞭解fork的讀者可以簡單的理解為使用者傳送給了伺服器查詢請求),分別是master節點(主節點)、負責map的節點(map節點)和負責reduce的節點(reduce節點)。主節點收到使用者的查詢請求之後,會為map節點分配查詢任務,每一個map節點只負責對一部分資料的查詢,這樣多個map節點可以並行地對整個資料庫進行查詢,從而提高效率。每個map節點對自己負責的資料查詢完畢之後,會將查詢到結果寫入本地的磁碟的中間檔案裡,供reduce節點讀取。reduce節點在map節點查詢完成後就透過網路遠端讀取map節點形成的中間檔案,去到各個map節點的查詢結果並作合併和排名等後處理操作,最終寫入到輸出檔案中,返回給使用者查詢結果。圖2展示了整個Map Reduce的流程。
什麼是分散式系統?——一個沒有回答完的問題
到這裡我們或許可以透過上述場景思考一個十分重要的問題了,即什麼是分散式系統?谷歌的Map Reduce系統當然算是一個分散式系統,我們能從中總結出來一些什麼特點,將其作為分散式系統的定義呢?比如有多個節點,它們相互協作,等等。而這只是從系統本身的角度來看的,如果從使用者的角度來看,使用者肯定不希望每次查詢的時候都要看一遍上述的執行流程,因此,對於使用者來說,分散式系統應該表現得像是一臺計算機一樣。而從系統的角度來說,主節點、map節點和reduce節點都必須做到相互配合協作才能夠準確無誤的完成上述流程,這其中就涉及到非常多複雜的因素了。
那分散式系統有沒有一個完整的定義呢?事實上,許多分散式系統領域的學者和大咖都曾在自己的著作中嘗試為分散式系統下一個定義,比如Distributed systems principles and paradigms一書的作者Andrew Tanenbaum給出的定義是“A distributed system is a collection of independent computers that appear to the users of the system as a single computer.”,而Needham–Schroeder協議的發明人Michael Schroeder給出的定義則是“A distributed system is several computers doing something together. Thus, a distributed system has three primary characteristics: multiple computers, interconnections, and shared state.”儘管上述定義都從某些方面描述了分散式系統的特質,但是沒有任何一個能夠說服大家,成為一個公認的完美的定義。
我相信,隨著學習的深入,每個人心中都會有一個屬於自己的完美的分散式系統的定義。但是在本系列博文中,一個大致可以概括我們所討論的內容的定義或許是這樣的。它概括了我們即將討論的若干議題。
A distributed system is a collection of entities, each of which is autonomous, programmable, **asynchronous **and failure-prone, and which communicate through an **unreliable **communication medium.
一個分散式系統是一組實體的集合,這組實體是自治的、可程式設計的、非同步的和能夠容錯的,並且透過不可靠的媒介進行通訊。這個定義給出了分散式系統應當滿足的一些基本的特點,目前我們生活中接觸絕大多數分散式系統都滿足這些特點。
所謂自治,指的是每一個實體都可以決定是否加入到分散式系統的工作任務或者決策中來而不受到其他實體的影響,而可程式設計,則表示每個實體都可以根據自己的邏輯和配置執行,非同步性則更多討論的是通訊,即通訊可以在任意時刻發生,且不保證訊息的最重可達,也不保證訊息到達的時間上限,能夠容錯則比較好理解,即如果分散式系統中的一些實體崩潰或者因為網路問題失去了聯絡,這個分散式系統仍能夠正常工作。不可靠的通訊媒介意味著實體之間的訊息傳遞可能會出現丟失、延遲、重複或順序錯亂等問題。這就是分散式系統自身需要滿足的要求和必須面臨的不可靠的環境。在這些看似合情合理卻又十分苛刻的條件下,構建一個能夠正常穩定執行的分散式系統,並不是一件簡單的事情。
分散式系統設計的目標
前文大致描述了分散式系統應該是什麼樣的,這一部分詳細介紹一下設計分散式系統的目標。總的來說,設計一個分散式系統,需要考慮九個方面的指標。它們分別是魯棒性、可用性、透明性、異質性、併發、高效、可擴充套件性、安全性和開放性。遺憾的是,目前沒有任何一種分散式系統能夠在上述九個目標上全部達到較好的表現。很多指標之間甚至是存在衝突的,比如安全性和開放性,魯棒性和可擴充套件性等等。以我們熟知的分散式系統——網際網路為例,網際網路的設計目標就只有一個,那就是可擴充套件性,而其他的指標對於網際網路而言,都是儘可能做(best effort)。下面分別介紹這九大目標的具體含義。
- 魯棒性:系統是否能適應節點的故障甚至崩潰,或者通道中訊息的丟失?
- 可用性:資料和服務是否總是能夠獲取
- 透明性:使用者是否對分散式系統的工作過程有所感知?
- 異質性:系統是否能夠容納不同型別的節點(比如裝置)?
- 併發:伺服器是否能夠同時處理多個客戶端的請求?
- 高效:系統是否足夠快?
- 可擴充套件性:系統是否能夠容納足夠多的節點?
- 安全性:系統是否能夠抵禦攻擊?
- 開放性:系統是否能夠接納新的服務或者裝置的接入?
這裡值得一提的是,雖然網際網路在設計的時候就只考慮擴充套件性,但是我們知道,計算機網路是分層的架構,在不同的層次可以保證不同的性質,而這是透過不同的協議來保證的,比如大家熟知的TCP協議和UDP協議,這是兩個傳輸層協議,但是設計的目標卻不一樣。TCP協議儘可能保證魯棒性和可用性,即總是讓對方確定收到了訊息,而UDP協議則犧牲掉了魯棒性轉而追求高效。這也是為什麼對實時性要求高的應用會在傳輸層選擇UDP協議的原因,這其中其實沒有什麼優劣次第,只是對不同應用有相應的取捨(trade-off)而已。
總結
- 谷歌的map reduce
- 分散式系統的一種定義
- 分散式系統的設計目標