1. 通信基礎 1.1. 每個分散式系統都包含通過網路進行通信的軟體組件 1.2. 硬體 1.2.1. 全球互聯網就是一臺異構機器,由不同類型的網路通信通道和設備組成,它們每秒將數百萬條消息通過網路傳送到預定目的地 1.2.2. 對於單個光纖鏈路,可以提供每秒超過70 Tbps的總帶寬 1.2.3. ...
1. 通信基礎
1.1. 每個分散式系統都包含通過網路進行通信的軟體組件
1.2. 硬體
-
1.2.1. 全球互聯網就是一臺異構機器,由不同類型的網路通信通道和設備組成,它們每秒將數百萬條消息通過網路傳送到預定目的地
-
1.2.2. 對於單個光纖鏈路,可以提供每秒超過70 Tbps的總帶寬
-
1.2.3. 廣域網的延遲更為複雜
- 1.2.3.1. 廣域網傳輸數據的距離可達數百乃至數千公裡,數據在光纖電纜中傳輸的最大速度是理論光速
-
1.2.4. 路由器是專用高速網路設備,它可以處理數百Gbps的網路流量,從傳入連接中提取數據並根據目的地將數據發送到不同的傳出網路連接
-
1.2.4.1. 家裡和辦公室中的WiFi路由器都是無線乙太網網路,使用802.11協議發送和接收數據
-
1.2.4.2. 使用最廣泛的WiFi協議是802.11ac(WiFi 5),它允許最大(理論)數據速率高達5400 Mbps
-
1.2.4.3. 最新的802.11ax協議,也稱WiFi 6,是由802.11ac技術演變的,聲稱已將吞吐量提高至9.6 Gbps
-
1.2.4.4. WiFi路由器的範圍是幾十米的數量級,會受到牆壁和地板等物理障礙的影響
-
-
1.2.5. 蜂窩無線技術使用無線電波將數據從手機發送到安裝在手機信號塔上的路由器,路由器通常通過電線連接到核心互聯網來進行消息路由
-
1.2.5.1. 5G基站的最大覆蓋範圍約為500 m
-
1.2.5.2. 4G可在10~15 km內提供可靠的接收
-
-
1.2.6. 一級網路是全球高速互聯網骨幹網
- 1.2.6.1. 大約有20家一級ISP(互聯網服務提供商)負責管理和控制全球流量
-
1.2.7. 二級ISP通常是區域性
- 1.2.7.1. 帶寬低於一級ISP,並通過三級ISP向客戶提供內容
-
1.2.8. 三級ISP是每月向你收取高額家庭互聯網費用的ISP
1.3. 軟體
-
1.3.1. 互聯網上的軟體系統使用IP(互聯網協議)套件進行通信
-
1.3.1.1. 互聯網是一個數據包交換網路,每個數據包都在網路中單獨路由
-
1.3.1.2. 因為網路數據包在發送方和接收方之間的傳輸過程中可能會丟失或延遲,所以可靠性是必需的
-
-
1.3.2. 四個抽象層
-
1.3.2.1. 數據鏈路層,定義了跨單個網段的數據通信方法
-
1.3.2.2. 網路層,指定定址和路由協議,使流量能夠穿越構成互聯網的獨立管理和控制的網路
1.3.2.2.1. 是互聯網協議家族中的IP層
-
1.3.2.3. 傳輸層,定義了可靠和儘力而為的主機到主機通信的協議
1.3.2.3.1. 是著名的TCP(傳輸控制協議)和UDP(用戶數據報協議)所在的層
-
1.3.2.4. 應用層,其中包含多個應用程式級協議
1.3.2.4.1. HTTP和SCP(安全複製協議)
-
-
1.3.3. IP
-
1.3.3.1. IP定義瞭如何在互聯網上為主機分配地址,以及如何在知道彼此地址的兩個主機之間傳輸消息
-
1.3.3.2. 互聯網上的每個設備都有自己的地址,也稱為IP地址
-
1.3.3.3. IP地址的位置可以在互聯網範圍的目錄服務DNS(功能變數名稱系統)中找到
1.3.3.3.1. DNS伺服器是分層組織的
1.3.3.3.2. 整個DNS資料庫在地理上高度複製,因此沒有單點故障,同時請求被分佈在多個物理伺服器上
-
1.3.3.4. 用於分配IP地址的技術稱為IPv4(互聯網通信協議第4版),它將被後繼者IPv6取代
1.3.3.4.1. IPv4是32位定址方案,由於連接到互聯網的設備數量不斷增加,不久的將來就會用完地址
-
1.3.3.5. IPv6是128位方案,提供(幾乎)無限數量的IP地址
-
1.3.3.6. IP也被稱為儘力而為的傳輸協議,它不會補償數據包傳輸期間可能發生的各種錯誤情況
1.3.3.6.1. 可能的傳輸錯誤包括數據損壞、數據包丟失和重覆
-
-
1.3.4. TCP
-
1.3.4.1. 一旦應用程式或瀏覽器發現了目標伺服器的IP地址,它就可以使用傳輸協議API發送消息
1.3.4.1.1. 這是使用TCP或UDP來實現的,它們是IP網路協議棧的流行標準傳輸協議
-
1.3.4.2. 面向連接的
-
1.3.4.3. 面向流的
-
1.3.4.4. 可靠的
-
1.3.4.5. TCP是面向連接的協議
1.3.4.5.1. 在應用程式之間交換任何消息之前,TCP使用三步握手在客戶端和伺服器應用程式之間建立雙向連接
-
1.3.4.6. 用於檢查數據包完整性的校驗和
-
1.3.4.7. 用於確保發送方不會因發送數據過快而淹沒慢速接收方的動態流量控制
-
1.3.4.8. 連同連接建立和確認,TCP成為一個重量級的協議,它在可靠性和效率之間爭取可靠性
-
-
1.3.5. UDP
-
1.3.5.1. UDP是一種簡單的無連接協議,它將用戶的程式暴露給不可靠的底層網路
-
1.3.5.2. 它無法保證消息傳遞按照規定的順序進行,甚至消息傳遞可能根本不會發生
-
1.3.5.3. 可以被認為是底層IP協議之上的一層薄薄的單板(層),併在原始性能和可靠性之間爭取性能
-
1.3.5.4. 非常適合許多現代應用程式,這些應用程式對異常丟失的數據包不敏感
1.3.5.4.1. 對於流媒體電影、視頻會議和游戲,用戶不太可能察覺到一個丟失的數據包
-
2. 遠程方法調用
2.1. 使用直接與傳輸層協議TCP和UDP交互的底層API來編寫分散式應用程式是完全可行的
2.2. 最常見的方法是調用標準化套接字型檔
- 2.2.1. 套接字型檔是一個底層的、難以使用的API
2.3. 套接字是客戶端和伺服器之間雙向網路連接的一個端點
-
2.3.1. 套接字由節點IP地址和埠的組合來標識
-
2.3.2. 埠是唯一的數字標識符,它允許節點支持在該節點上運行的多個應用程式的通信
-
2.3.3. 每個IP地址都可以支持65535個TCP埠和另外65535個UDP埠
2.4. 可以直接向套接字API寫入分散式應用程式,它是操作系統的核心組件
2.5. 註冊表是一種簡單的目錄服務,通過它,客戶端可以查找位置(網路地址和對象引用),並簡單地提供邏輯名稱來獲取RMI伺服器引用,邏輯名稱在註冊表中已經與伺服器的引用相關聯
2.6. 跨編程語言的編組(客戶端使用一種編程語言,伺服器端使用另一種編程語言)可能會導致錯誤,因為類型在不同語言中的表示方式不同,存在微妙的不相容性
2.7. 多數現代系統都是圍繞基於HTTP並使用JSON表示參數的更簡單協議來構建的
- 2.7.1. HTTP動詞(PUT、GET、POST等)具有映射到特定URL的關聯語義,而不是操作名稱
3. 局部故障
3.1. 分散式系統的組件通過網路通信
3.2. 非同步網路特點
-
3.2.1. 節點可以隨時向其他節點發送數據
-
3.2.2. 網路是半雙工的,這意味著一個節點發送請求必須等待另一個節點的響應。涉及兩個獨立的通信
-
3.2.3. 節點之間傳輸數據的時長是變化的,受網路擁塞、動態數據包路由和瞬態網路連接故障等因素影響
-
3.2.4. 接收節點可能因軟體或機器崩潰而無法使用
-
3.2.5. 數據可能會丟失
-
3.2.6. 節點沒有完全一樣的內部時鐘;節點之間是不同步的
3.3. 同步網路則不一樣,本質上是全雙工的,同時在兩個方向傳輸數據,每個節點的時鐘是同步的
3.4. 客戶端是否收到響應,以及何時收到響應,這被稱為局部故障處理
3.5. 冪等性
-
3.5.1. 冪等操作執行多次的結果與執行一次的結果一致
-
3.5.2. 沒有更改持久狀態的請求自然是冪等的
- 3.5.2.1. 意味著所有讀取請求本質上都是安全的,不需要在伺服器上執行額外的工作
3.6. 更新持久狀態則是另一回事
- 3.6.1. 系統需要設計一種機制,使得客戶端重覆的請求不會導致任何狀態變化,並且可以被伺服器檢測到
3.7. 伺服器狀態發生變化的端點必須是冪等的
3.8. 構建冪等操作的方法
-
3.8.1. 客戶端在所有改變狀態的請求中包含一個唯一的冪等鍵
-
3.8.2. 伺服器收到請求時,會檢查它是否包含資料庫中出現過的冪等性鍵值,而資料庫是專門為實現冪等性而設計的
-
3.8.3. 如果冪等鍵在資料庫中,表明此請求是來自客戶端的重試,不應處理
3.9. 存儲冪等鍵的資料庫的實現
-
3.9.1. 單獨的資料庫表或集合,與應用程式數據一起存儲在事務資料庫中
-
3.9.2. 專用的資料庫,提供極低查找延遲,例如簡單的鍵值存儲
3.10. 與應用程式數據不同,冪等鍵不必永遠保留
-
3.10.1. 一旦客戶端收到操作成功的確認,就可以丟棄冪等鍵了
-
3.10.2. 達成此目的最簡單的方法是在特定時間段後自動從存儲中刪除冪等鍵,具體取決於應用程式需求和請求量
3.11. 冪等API實現必須確保應用程式狀態已修改和冪等鍵已存儲,兩者均已發生API才能成功
3.12. 從本質上講,事務確保了嚴格一次的操作(exactly-once semantics for operations),保證了所有消息始終只處理一次
-
3.12.1. 嚴格一次並不意味著沒有消息傳輸失敗、重試和應用程式崩潰,它們都是不可避免的
-
3.12.2. 重要的是重試最終會成功,結果總是一樣的
-
3.12.3. 嚴格一次(exactly-once)消息傳遞需要防止重覆,需要在可靠性和較慢的性能之間進行權衡
3.13. 最多一次(at-most-once)消息傳遞速度快且不可靠——這是UDP協議提供的
3.14. 至少一次(at-least-once)消息傳遞是TCP/IP提供的保證,意味著重覆是不可避免的
4. 分散式系統中的共識
4.1. 事實上,不能保證一定會達成協議是可以證明的
4.2. 局部失敗類似於丟失消息和確認
4.3. FLP不可能原理
-
4.3.1. 事實上,存在崩潰故障的非同步網路上,消息可以延遲但不會丟失,在有限時間內不可能達成共識
-
4.3.2. FLP是最壞的情況
4.4. 在非同步網路上無法保證在無限消息延遲的情況下達成共識
-
4.4.1. 實際上,分散式系統總是會達成共識
-
4.4.2. 儘管我們的網路是非同步的,但我們可以在消息延遲上建立合理的界限併在超時後重試
4.5. 拜占庭故障,在分散式系統中尤為險惡
5. 分散式系統中的時間
5.1. 分散式系統中的每個節點都有自己的內部時鐘
-
5.1.1. 如果每台機器上的時鐘都是完全同步的,我們就可以簡單地比較節點間事件的時間戳,確定它們發生的精確順序
-
5.1.2. 受溫度或電壓變化等環境條件影響,各個節點上的時鐘會漂移
-
5.1.3. 每台機器的時間漂移量各不相同,但每天漂移10~20 s的現象並不少見
5.2. 時間服務是準確的時間源
5.3. 使用最廣泛的時間服務是NTP(網路時間協議)
-
5.3.1. 提供了跨越全球的分層組織時間伺服器集合
-
5.3.2. 全球約有300台根伺服器,它們的時間是最準確的
-
5.3.3. 下一級時間伺服器(大約20000個)定期(幾毫秒內)與根伺服器同步
-
5.3.4. 整個層次結構最多15級
-
5.3.5. 全球有超過175000台NTP伺服器
-
5.3.6. 節點上的時間由與一個或多個NTP伺服器進行的UDP消息交換來同步
- 5.3.6.1. 消息帶有時間戳,通過消息交換估算消息傳輸所用的時間
-
5.3.7. 時鐘的重置可以將本地節點時間向前或向後移動
- 5.3.7.1. 如果我們的應用程式正在計算事件所花費的時間(例如,計算事件響應時間),如果NTP協議已設置本地時間並導致時間倒退,則事件的結束時間可能早於開始時間
5.4. 日曆鐘
- 5.4.1. 日曆鐘(time of day clock)是自1970年1月1日午夜以來的毫秒數
5.5. 單調時鐘
- 5.5.1. 單調時鐘(monotonic clock)是自過去未指定時間點以來的時間量(以秒和納秒為單位)
5.6. 應用程式可以使用NTP服務來確保系統中每個節點上的時鐘緊密同步
-
5.6.1. 通常會以一小時到一天的時間間隔重新同步時鐘,確保時鐘的時間值保持接近
-
5.6.2. 如果應用程式確實需要準確瞭解不同節點上事件發生的順序,那麼時鐘漂移將使其充滿危險
-
5.6.3. 我們的應用程式不能依賴不同節點上事件的時間戳來表示事件的實際順序
- 5.6.3.1. 即使時鐘漂移一兩秒也會導致跨節點時間戳無法比較
5.7. Chrony支持NTP協議,但比NTP準確性更高和擴展性更好
6. 要點
6.1. 解決方案分佈在不同位置的多台機器上,每台機器並行處理事件,且它們之間通過網路交換消息
6.2. 分散式系統中的通信可以透明地穿過許多不同類型的底層物理網路,包括WiFi、無線網路、廣域網和區域網
6.3. 互聯網協議棧通過IP和TCP協議的組合確保跨異構網路的可靠通信
6.4. 使用RMI/RPC技術構建TCP/IP層,為客戶端/伺服器通信提供抽象層,採用本地方法/過程調用的方式調用伺服器介面
6.5. 在非同步網路中,存在崩潰故障的情況下,有限時間內不可能在多個節點之間就狀態達成一致或達成共識
6.6. 沒有完全可靠的全局時間源可供應用程式中的節點同步其行為
-
6.6.1. 各個節點上的時鐘各不相同,不能用於精確的比較
-
6.6.2. 應用程式無法通過比較不同節點上的時鐘來確定事件的順序