淺談分散式計算的開發與實現(1)

發表於2015-11-17

閱讀目錄:

  1. 介紹
  2. 利用分片演算法
  3. 利用訊息佇列
  4. Hadoop簡介
  5. MapReduce
  6. 離線計算

介紹

分散式計算簡單來說,是把一個大計算任務拆分成多個小計算任務分佈到若干臺機器上去計算,然後再進行結果彙總。 目的在於分析計算海量的資料,從雷達監測的海量歷史訊號中分析異常訊號(外星文明),淘寶雙十一實時計算各地區的消費習慣等。

海量計算最開始的方案是提高單機計算效能,如大型機,後來由於資料的爆發式增長、單機效能卻跟不上,才有分散式計算這種妥協方案。 因為計算一旦拆分,問題會變得非常複雜,像一致性、資料完整、通訊、容災、任務排程等問題也都來了。

舉個例子,產品要求從資料庫中100G的使用者購買資料,分析出各地域的消費習慣金額等。 如果沒什麼時間要求,程式設計師小明就寫個對應的業務處理服務程式,部署到伺服器上,讓它慢慢跑就是了,小明預計10個小時能處理完。 後面產品嫌太慢,讓小明想辦法加快到3個小時。

平常開發中類似的需求也很多,總結出來就是,資料量大、單機計算慢。 如果上Hadoop、storm之類成本較高、而且有點大才小用。 當然讓老闆買更好的伺服器配置也是一種辦法。

利用分片演算法

小明作為一個有追求有理想的程式設計師,決定用介於單機計算和成熟計算框架的過度解決方案,這樣成本和需求都能滿足了。 分散式計算的核心在於計算任務拆分,如果資料能以水平拆分的方式,分佈到5臺機器上,每臺機器只計算自身的1/5資料,這樣即能在3小時內完成產品需求了。

如上所述,小明需要把這些資料按照一定維度進行劃分。 按需求來看以使用者ID劃分最好,由於使用者之間沒有狀態上的關聯,所以也不需要事務性及二次迭代計算。 小明用簡單的hash取模對id進行劃分。

這樣程式可以分別部署到5臺機器上,然後程式按照配置只取對應餘數的使用者id,計算出結果併入庫。 這種方式多機之間毫無關聯,不需要進行通訊,可以避免很多問題。 機器上的程式本身也不具備分散式的特性,它和單機一樣,只計算自身獲取到的資料即可,所以如果某臺機器上程式崩潰的話,處理方式和單機一樣,比如記錄下處理進度,下次從當前進度繼續進行後續計算。

利用訊息佇列

使用分片方式相對比較簡單,但有如下不足之處。

  • 它不具有負載均衡的能力,如果某臺機器配置稍好點,它可能最先計算完,然後空閒等待著。也有可能是某些使用者行為資料比較少,導致計算比較快完成。
  • 還有一個弊端就是每臺機器上需要手動更改對應的配置, 這樣的話多臺機器上的程式不是完全一樣的,這樣可以用遠端配置動態修改的辦法來解決。

小明這種方式引入了個第三方,訊息佇列。 小明先用一個單獨的程式把使用者資訊推送到訊息佇列裡去,然後各臺機器分別取消費這個佇列。 於是就有了3個角色:

  • 推送訊息的,簡稱Master。
  • 訊息佇列,這裡以Rabbitmq為例。
  • 各個處理程式,簡稱Worker或Slave都行。

雖然僅僅引入了個第三方,但它已經具備了分散式計算的很多特性。

  1. 計算任務分發。 Master把需要計算的使用者資料,不斷的推送訊息佇列。
  2. 程式一致性。 Worker訂閱相同的訊息佇列即可,無需更改程式程式碼。
  3. 任意擴容。 由於程式完全一樣,意味著如果想要加快速度,重複部署一份程式到新機器即可。 當然這是理論上的,實際當中會受限於訊息佇列、資料庫儲存等。
  4. 容災性。 如果5臺中某一臺程式掛了也不影響,利用Rabbitmq的訊息確認機制,機器崩潰時正在計算的那一條資料會在超時,在其他節點上進行消費處理。

Hadoop簡介

Hadoop介紹已經相當多了,這裡簡述下比如:”Hadoop是一套海量資料計算儲存的基礎平臺架構”,分析下這句話。

  • 其中計算指的是MapReduce,這是做分散式計算用的。
  • 儲存指的是HDFS,基於此上層的有HBase、Hive,用來做資料儲存用的。
  • 平臺,指可以給多個使用者使用,比如小明有一計算需求,他只需要按照對應的介面編寫業務邏輯即可,然後把程式以包的形式釋出到平臺上,平臺進行分配排程計算等。 而上面小明的分散式計算設計只能給自己使用,如果另外有小華要使用就需要重新寫一份,然後單獨部署,申請機器等。Hadoop最大的優勢之一就在於提供了一套這樣的完整解決方案。

下面找了介紹Hadoop的概覽圖,跟小明的設計做對比下:

  • 圖中“大資料計算任務” 對應小明的100G使用者資料的計算任務。
  • ”任務劃分“ 對應Master和訊息佇列。
  • “子任務” 對應Worker的業務邏輯。
  • ”結果合併“ 對應把每個worker的計算結果入庫。
  • “計算結果” 對應入庫的使用者消費習慣資料。

PS:為了方便描述,把小明設計的分散式計算,叫做小和尚。

MapReduce

由於MapReduce計算輸入和輸出都是基於HDFS檔案,所以大多數公司的做法是把mysql或sqlserver的資料匯入到HDFS,計算完後再匯出到常規的資料庫中,這是MapReduce不夠靈活的地方之一。 MapReduce優勢在於提供了比較簡單的分散式計算程式設計模型,使開發此類程式變得非常簡單,像之前的MPI程式設計就相當複雜。

狹隘的來講,MapReduce是把計算任務給規範化了,它可以等同於小和尚中Worker的業務邏輯部分。 MapReduce把業務邏輯給拆分成2個大部分,Map和Reduce,可以先在Map部分把任務計算一半後,扔給Reduce部分繼續後面的計算。 當然在Map部分把計算任務全做完也是可以的。 關於Mapreduce實現細節部分不多解釋,有興趣的同學可以查相關資料或看下樓主之前的C#模擬實現的部落格【探索C#之微型MapReduce

如果把小明產品經理的需求放到Hadoop來做,其處理流程大致如下:

  1. 把100G資料匯入到HDFS
  2. 按照Mapreduce的介面編寫處理邏輯,分Map、Reduce兩部分。
  3. 把程式包提交到Mapreduce平臺上,儲存在HDFS裡。
  4. 平臺中有個叫Jobtracker程式的角色進行分發任務。 這個類似小和尚的Master負載排程管理。
  5. 如果有5臺機器進行計算的話,就會提前執行5個叫TaskTracker的slave程式。 這類似小和尚worker的分離版,平臺把程式和業務邏輯進行分離了, 簡單來說就是在機器上執行個獨立程式,它能動態載入、執行jar或dll的業務邏輯程式碼。
  6. Jobtracker把任務分發到TaskTracker後,TaskTracker把開始動態載入jar包,建立個獨立程式執行Map部分,然後把結果寫入到HDFS上。
  7. 如果有Reduce部分,TaskTracker會建立個獨立程式把Map輸出的HDFS檔案,通過RPC方式遠端拉取到本地,拉取成功後,Reduce開始計算後續任務。
  8. Reduce再把結果寫入到HDFS中
  9. 從HDFS中把結果匯出。

這樣一看好像是把簡單的計算任務給複雜化了,其實如果只有幾臺計算任務的話,使用Mapreduce確實是殺雞用牛刀了。 如果有TB、PB級別的資料、跑在成百上千臺計算節點上,Mapreduce的優勢才會體現出來。 其計算框架圖架構如下:

離線計算

通常稱Mapreduce及小和尚這種計算為離線計算,因為它對已經持久化的檔案資料進行計算,不能實時響應。 還有個原因就是它的處理速度比較慢,它的輸入和輸出源都是基於HDFS設計,如果資料不是一開始就寫入到HDFS上,就會涉及到資料匯入匯出,這部分相對耗費時間。 而且它的資料流動是基於檔案系統的,Map部分輸出的資料不是直接傳送到Reduce部分,而是先寫入HDFS再進行傳送。

處理速度慢也是Mapreduce的不足之處,促使了後面實時計算的誕生。

另外個缺點是Mapreduce的計算任務流比較單一,它只有Map、Reduce兩部分。 簡單的可以只寫一部分邏輯來解決,如果想拆分成多個部分,如邏輯A、邏輯B、邏輯C等, 而且一部分計算邏輯依賴上一次計算結果的話,MapReduce處理起來就比較困難了。 像storm框架解決此類問題的方案,也稱為流式計算,下一章繼續補充。

相關文章