前言

本系列是源於 「碼農翻身」 所屬知識星球發起的讀書活動,由大佬 @我的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 站中文翻譯視頻地址

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

相關文章