初識分散式:MIT 6.284系列(一)

Kerwin發表於2020-08-03

前言

本系列是源於「碼農翻身」所屬知識星球發起的讀書活動,由大佬 @我的UDP不丟包 推薦而來,這次的讀書活動有一些另類,我們拋棄了傳統的書籍,開始攻略最高學府的研究生頂級課程 <6.824>,該課程是很多年前的蠕蟲病毒發明者Robert Morris大佬授課,歸屬於麻省理工大學,授課方式主要是:視訊 + Lab 實驗(Go 語言) + 論文,全程英語,難度較大。

分散式系統的判斷依據

  • multiple cooperating computers (多臺計算機協作)
  • storage for big web sites, MapReduce, peer-to-peer sharing (大規模資料集運算,如:MapReduce,或點對點共享)
  • lots of critical infrastructure is distributed (系統的絕大部分基礎設施是分散式的)

MapReduce:大規模資料集計算系統,比如計算從 1 加到 1000 億,可以單臺計算機計算,也可以利用該技術分散到多臺計算機計算然後合併結果,極大的提高效率

為什麼需要分散式系統

  • to increase capacity via parallelism (通過並行增加系統效能)
  • to tolerate faults via replication (通過複製備份增加系統容錯)
  • to place computing physically close to external entities (可以將計算放在離外部實體更近的地方)
  • to achieve security via isolation (可以通過隔離增加系統的安全)

容錯:針對於容錯,主要是兩點,一是可用性,二是可恢復性

對於分散式系統來說,一般不會全部伺服器同時癱瘓,因此無論是服務可用還是資料安全,都比單體服務更有保障。

分散式的難點

  • 需要額外注意併發程式設計,對開發人員的能力要求直線上升
  • 系統內的相互作用非常複雜
  • 意想不到的錯誤:區域性錯誤
  • 預期效能和實際效能往往不符

區域性錯誤:假設一臺機器每天出故障的概率是千分之一,在單體應用中,可能很長時間可以工作,但是在分散式系統中,裝置數量急劇上升,每天都可能有裝置出現故障,這就是所謂的區域性錯誤,很難排查,也幾乎無法避免

此處展示一張單體應用和分散式應用的對比圖,圖片出自:《極客時間 · 左耳聽風》

分散式系統的解決方案

巨集觀目標

我們需要設計一系列能夠遮蔽分散式系統複雜性的抽象

為什麼要設立此目標?

因為分散式系統本身已足夠複雜,因此必須簡化使用方式

簡化使用方式和抽象有什麼關係?

我目前認可的最完美抽象是:檔案

“UNIX 檔案本質上就是一大袋位元組。” —— 《UNIX 程式設計藝術》

在 Unix 中,任何可讀/寫也就是有 I/O 的裝置,無論是檔案,socket,驅動,在開啟裝置之後都有一個對應的檔案描述符。Unix 將對這些裝置的讀寫簡化在 read/write 中,換言之,你只需要把開啟的檔案描述符傳給這兩個函式,作業系統核心知道如何根據這個檔案描述符得到具體裝置資訊,內部隱藏了對各種裝置進行讀寫的細節,所有這些對使用者都是透明的,你只需要開啟它,得到 fd,再進行相應的操作就夠了。

研究角度

  • 實現方式。
    • RPC 遠端呼叫,執行緒和併發控制
  • 效能:
    • 通常我們想要提供一個效能可以擴充套件的系統。
    • 可以通過簡單增加系統的電腦數量來增強並行能力,從而部分擴充套件系統的效能:
      • 當沒有複雜互動的時候這麼做很有效
      • 可以不用請昂貴的程式設計師來重新設計系統。
    • 簡單增加系統內電腦數量並不能一直增加系統效能:
      • 當電腦數量變得很多的時候,負載不均,系統內每臺電腦效能不均,無法並行執行的程式碼,初始化的互動都會降低系統的效能。
      • 來自共享資源的訪問也會造成效能瓶頸,比如網路通訊或者資料庫等
    • 同時效能也並不能總是靠增加系統內電腦數量達成:
      • 比如來自單一使用者請求的快速響應時間
      • 比如所有使用者都想要更新同一個資料。
      • 通常這些情況需要更好的程式設計而不是更多的電腦。
  • 容錯:
    • 大量的伺服器 + 大型的系統通常代表著總有錯誤會發生
    • 我們需要嚮應用程式隱藏這些錯誤
    • 我們通常想要讓系統擁有可用性和可恢復性
      • 可用性:即使錯誤發生了,系統還是可以繼續執行
      • 可恢復性:當錯誤被修復之後,系統可以恢復執行
    • 通常可以用備用的伺服器來增加容錯
  • 一致性:
    • 通常想要達成正確工作的系統十分困難:
      • 伺服器和它的備份伺服器之間很難保持一致,代價太高
      • 客戶端可能會在中途出錯。
      • 伺服器可能會在處理之後回覆之前崩潰
      • 不佳的網路可能會使得正常的伺服器無法提供服務
    • 一致性和效能通常是矛盾的:
      • 高一致性需要各種基礎設定之間大量的通訊
      • 許多設計為了提升效能被迫只提供弱一致性

一致性:一致性問題貌似是最難以解決的問題,因為它本質包含了效能,容錯,資料一致性等等諸多要素

我們前文說過,為了考慮容錯容災機制,需要資料進行備份,那麼在分散式系統中,A 服務修改了 A 資料庫的值,B 資料庫的值要不要跟著改,是立即跟著改,還是延遲跟著改,在同步修改中出問題了怎麼辦,在非同步修改中出問題了怎麼辦

最終業界也很難解決相應的問題,因此現在主流的方式是:最終一致性

即允許短時間內資料不一致,通過最終一致性保證效能和資料安全的兼顧

持續腦圖

檔案分享地址:https://www.processon.com/view/link/5f1db0230791291b99680fa0

下一章內容

接下來的一章,我們將進行 <6.824> 中的 Lab 1,即實現一個簡單的MapReduce系統,該系統將採用 Go 語言構建

Go 語言是近些年非常熱門的語言之一,其價值個人感覺大於被炒的火熱的 Python

本章要求

  • 瞭解分散式系統的由來及面臨的挑戰
  • 瞭解<6.824>課程中涉及的分散式系統解決方案
  • 搭建 Go 語言環境,寫出 HelloWorld 即可(語法層面及 MR 實現將在下章學習)

最後

相關資源:

Go 官方映象站

Go 語言 IDE

Go 語言環境搭建教程

Go 語言初識 + HelloWorld

MIT 課程表主頁

B 站中文翻譯視訊地址

如果覺得對你有用的話,不要忘記點個贊啊~ 也可以掃描二維碼關注我,一起朝著技術人的頂峰前進!

相關文章