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. 應用程式無法透過比較不同節點上的時鐘來確定事件的順序