01

為什麼需要模型?先搞懂物理模型

模型不是拿來完美描述現實,而是拿來讓你我對「分散式系統長什麼樣子」講同一種語言

真實世界很殘酷,設計者要扛四種麻煩

上一章讓你看到分散式系統五花八門——搜尋引擎、線上遊戲、金融交易。這一章要處理一個更根本的問題:一個要在真實環境長期運作的系統,得在各式各樣的狀況與威脅下都還能正確工作。課本把設計者要面對的麻煩分成四大類:

使用方式千變萬化——有網頁一天被點好幾百萬次,行動裝置時連時斷,多媒體應用又要超高頻寬、超低延遲;環境差異極大——硬體、作業系統、網路全都不一樣(異質性 heterogeneity),規模可能從十幾台到上百萬台電腦;內部問題——時鐘不同步、資料更新互相衝突、各種軟硬體失效;外部威脅——對資料完整性與機密性的攻擊、阻斷服務攻擊。

⚠️
面向太多,人腦會當機

光看這四類麻煩就頭暈了,更別說同時處理。所以課本的解法不是列一張更長的檢查清單,而是換一種思考工具——用描述性模型(descriptive model)把複雜度馴服下來。

直接讀原文,旁邊就是白話

這是本章開場,作者對「三種模型為什麼存在」的正式交代。原文放左邊,白話導讀放右邊——先讀懂原文的氣口,再看整段在說什麼。

原文 · DSCD Ch.2 This chapter provides an explanation of three important and complementary ways in which the design of distributed systems can usefully be described and discussed. Physical models consider the types of computers and devices that constitute a system and their interconnectivity, without details of specific technologies. Architectural models describe a system in terms of the computational and communication tasks performed by its computational elements. Fundamental models take an abstract perspective in order to describe solutions to individual issues faced by most distributed systems.
白話導讀

這一章要介紹三種重要、而且互補的方式,用來描述與討論分散式系統的設計。物理模型只看「有哪些電腦與裝置、怎麼連起來」,故意不管具體是哪家廠牌的技術;架構模型看軟體元件各自負責什麼運算與通訊任務,怎麼分工;基礎模型則抽象地去描述大多數分散式系統都會遇到的共同難題(像時間、失效、安全)該怎麼解。三種模型不是三選一,而是像三張不同用途的藍圖,疊在一起才看得到系統的全貌。

🗺️
模型就像地圖

地圖刻意省略樹木與行人,只留下道路與地標,反而讓你更容易找路。模型也一樣——刻意省略細節,讓我們更容易推理系統的行為,而不是被雜訊淹沒。

蓋一棟大樓,需要好幾張圖

想像你要描述一棟大樓,一張圖是不夠的:結構圖畫出有幾根柱子、幾片牆、用什麼建材;平面配置圖畫出客廳、廚房、臥室各自負責什麼、彼此怎麼連通;消防規範抽象地規定「火災時怎麼逃生」「結構要承受多大地震」。三張圖描述同一棟樓的不同面向,缺一不可——這正是三種模型互補(complementary)的意思。

🏗️
物理模型 Physical model

最具體、看硬體:有哪些電腦、裝置與網路互連?故意不管是哪家廠牌的技術——對應大樓的結構圖。

🧩
架構模型 Architectural model

看軟體分工:哪些元件在做運算與通訊?彼此怎麼分工?對應大樓的平面配置圖。

📐
基礎模型 Fundamental model

最抽象、看本質難題:互動、失效、安全各有什麼特性與保證?對應大樓的消防與結構規範。

🔑
基礎模型還會再細分

基礎模型底下又分三個子模型:互動模型(效能與時間)、失效模型(故障分類)、安全模型(威脅與防禦)。後面章節會一個一個展開。

招牌互動:物理模型的三個世代,規模怎麼爆炸

先把最精簡的基準物理模型(baseline physical model)釘死:就是一組可擴充的電腦節點,由網路互連來傳遞訊息。從這條基準線出發,課本點出三個世代——規模與異質性一路躍進。

早期
早期分散式系統(1970 末-1980 初)

因區域網路(多半是 Ethernet)而興起,通常只有 10-100 個節點,服務很少(共享印表機、檔案、email),系統大致同質(homogeneous),開放性還不是重點——就像一個十幾戶人家、彼此都認識、房子蓋得差不多的小村莊。

網際網路規模
網際網路規模系統(1990 年代)

隨網際網路爆發成長(例如 Google 1996 年上線),節點數量暴增、跨組織、高度異質——網路、電腦架構、作業系統、語言、開發團隊通通不一樣,因此開始重視開放標準與middleware(中介軟體),就像大城市人口暴增、來自四面八方,需要交通號誌與通用規範來維持秩序。

當代
當代分散式系統

行動運算、普及運算(ubiquitous computing)、雲端/叢集運算興起,節點可達數十萬台,異質性再升級——就像超級都會圈,有人帶著手機到處移動,連洗衣機都連網,還有一整片合作供電的電廠。

🏙️
城市越大,越需要規則

從小村莊到超級都會圈,規模與居民背景差異越來越大,越需要通用規範來協調不同背景的居民——這正是為什麼「開放性」與「服務品質」隨著世代越來越被重視。

當代物理模型:三股趨勢,各打破一個舊假設

早期系統裡的節點通常是桌機,相對固定不動、獨立自主。當代三股趨勢,一個接一個打破了這個假設:

📱
行動運算 Mobile computing

打破「節點固定不動」——筆電、手機到處移動,因此需要 service discovery(服務發現)與自發互通的能力。

🧺
普及運算 Ubiquitous computing

打破「節點是獨立的電腦」——把運算嵌入日常物件與環境,例如智慧家庭裡的洗衣機也在運算。

☁️
雲端/叢集運算

打破「每個節點各自獨立負責一個角色」——一群節點合力提供同一服務,例如 Google 搜尋背後是一整個叢集。

當系統大到極致,甚至會變成系統的系統(system of systems)——由多個本身就是完整系統的子系統合作組成。課本舉的例子是洪水預測系統:感測器網路監測河川,叢集電腦跑模擬,另一套系統再透過手機發早期警報,三者各自獨立卻合作完成任務。

🌊
系統的系統,就像 network of networks

網際網路本身就是「網路的網路」;系統的系統是同一個道理套用到更高一層——每個子系統自己就能獨立運作,合作時又拼出一個更大的能力。

小試身手

把「三種模型分工」和「物理模型三世代」放進腦子裡,來兩題檢查一下:

某團隊想描述一個分散式系統「有哪些電腦、行動裝置以及它們之間的網路如何連接」,但刻意不討論用的是哪家廠牌的技術。他們最該使用哪種模型?
洪水預測系統由感測器網路、跑模擬的叢集電腦、手機警報系統三者合作,各自獨立卻共同完成防洪任務。這最能說明哪個概念?
📡
下一站:架構模型的第一道問題

搞懂了物理世界長什麼樣子,接下來要問:誰在通訊、它們又是怎麼通訊的?往下捲。

02

誰在通訊、怎麼通訊:架構模型的第一道問題

先搞懂「誰在通訊」,再搞懂「怎麼通訊」——這是讀懂任何分散式架構圖的兩把鑰匙

看懂一張架構圖,其實只要問四個問題

面對一個分散式系統,想拆解它的骨架,課本說先問四個問題:什麼在通訊(實體)?怎麼通訊(範式)?它們扮演什麼角色與責任?又怎麼放置到實體基礎設施上?這一站,我們先啃第一個——也是最根本的一個:什麼在通訊。

答案可以從兩種角度看。系統觀點很老實:通訊的實體通常就是process(行程)——所以分散式系統常被想成「一堆行程+行程間通訊」。問題觀點則更貼近你寫程式時的感覺,提出了 object、component、web service 三種更好用的抽象。

🧩
兩個系統觀點的小提醒

在感測器網路這類原始環境裡,作業系統可能根本不支援 process 抽象,這時通訊實體只能退回到node(節點)這一層。另外,多數環境裡 process 還會搭配thread(執行緒),嚴格說來,真正收送訊息的端點常常是 thread,不是 process 本身。

直接讀原文:通訊實體的三個問題觀點抽象

這段是課本從「系統觀點」過渡到「問題觀點」的關鍵段落,把 object、component、web service 三個抽象一次性交代清楚。原文放左邊,白話放右邊。

原文 · Distributed Systems Ch.2 From a system perspective, the answer is normally very clear in that the entities that communicate in a distributed system are typically processes. Objects are accessed via interfaces, with an associated interface definition language (or IDL) providing a specification of the methods defined on an object. The key difference is that components specify not only their (provided) interfaces but also the assumptions they make in terms of other components/interfaces that must be present for a component to fulfil its function. Web services are intrinsically integrated into the World Wide Web, using web standards to represent and discover services.
白話翻譯

從系統觀點看,答案很單純:分散式系統裡真正在通訊的實體,通常就是 process。

object 是透過 interface(介面)存取的,還有一份專門描述「這個物件能做什麼方法」的 IDL(介面定義語言)規格。

component 跟 object 最關鍵的差別是:它不只講清楚自己「提供」什麼介面,還把自己「需要」哪些其他 component/介面才能正常運作,也一併寫進合約。

web service 本質上就是活在全球資訊網裡的東西,用 Web 的標準來描述、也讓別人能發現這個服務。

🤝
生活妙喻:找人合作做事

把這三種抽象想成你要合作的對象:object 像一位專業師傅,你透過一張「服務清單」(interface)知道他會做哪些事;component 像一位更負責任的外包廠商,他不只列出「我提供什麼」,還老實講「我需要你先準備好哪些東西」——等於給你一份完整合約,沒有藏起來的隱性需求;web service 則像一家掛在網路黃頁上的公司,用網址當地址,常常跨公司邊界做生意。

招牌互動一:四個通訊實體,各是誰的抽象?

process、object、component、web service ——把它們拖到最貼切的描述上,配完按「對答案」。

process(行程)
object(物件)
component(元件)
web service(Web 服務)
系統觀點下最基本的通訊實體——正在執行的程式,有自己私有的狀態;通常還搭配 thread 一起工作
拖到這裡
透過 interface(IDL 描述)存取,讓你用物件導向的方式自然分解問題,只公開「提供」什麼方法
拖到這裡
除了公開「提供」的介面,還明示自己「需要」哪些其他介面才能運作,消除隱藏相依性,方便第三方組裝
拖到這裡
用 URI 當地址、以 XML 等 Web 標準對外溝通,常跨組織邊界,把服務組合成加值的 B2B 整合
拖到這裡
📋
一張對照表記住四個抽象

process/thread 靠作業系統支撐,是任何分散式系統的底層;object 靠 interface(IDL)存取,適合組織內物件導向系統;component 在 interface 之外明示相依性,適合第三方放心組裝;web service 靠 URI+XML/Web 標準,天生適合跨組織的 B2B 整合。

搞懂「誰在通訊」之後,換問「怎麼通訊」

知道了通訊實體,課本接著把「怎麼通訊」分成三大類:行程間通訊(IPC)遠端呼叫(remote invocation)間接通訊(indirect communication)。原文先講遠端呼叫和間接通訊的根本差異:

原文 · Distributed Systems Ch.2 Communication represents a two-way relationship between a sender and a receiver with senders explicitly directing messages/invocations to the associated receivers. Senders do not need to know who they are sending to (space uncoupling). Senders and receivers do not need to exist at the same time (time uncoupling). In RPC, procedures in processes on remote computers can be called as if they are procedures in the local address space.
白話翻譯

遠端呼叫這一類,通訊是寄件人跟收件人之間明確的雙向關係——寄件人清楚知道要把訊息/呼叫送給誰。

間接通訊則相反:寄件人不必知道收件者是誰(空間解耦),寄件人和收件人也不必同時存在(時間解耦)。

以 RPC 來說,遠端電腦上 process 裡的程序,可以被當成本地位址空間裡的程序直接呼叫——分散的細節全被藏起來了。

下面這張圖,把三大通訊範式排在一起,點一下每個方塊,看看它的解耦程度與代表技術。

IPC 行程間通訊
遠端呼叫 RPC・RMI
間接通訊
點擊上方元件查看說明

招牌互動二:看一次 RPC 呼叫,怎麼「隱藏」分散的細節

RPC(遠端程序呼叫)最了不起的地方,就是讓你感覺不到「這是遠端」。按「下一步」,看一次呼叫怎麼在 client 和 server 之間跑一趟。

🖥️
Client process
⚙️
Server process
按「下一步」開始
☎️
遠端呼叫像打電話

你直接撥給某個人(明確指定收件者),雙方必須同時在線,你也知道對方是誰。RPC、RMI(遠端方法呼叫)更厲害的地方,是它讓這通越洋電話聽起來就像對方在隔壁房間。

間接通訊像公佈欄或郵局信箱

如果遠端呼叫是打電話,那間接通訊就是留言板:寄信的人不必知道誰會來看(空間解耦),寄信的人跟讀信的人也不必同時存在(時間解耦)。課本列出五種間接通訊技術,各自解決不同的場景。

1
group communication(群組通訊)

一對多——訊息送給一個「群組」,用群組識別碼代表,加入群組才會收到訊息,寄件人不需要知道每個收件者是誰。

2
publish-subscribe(發布—訂閱)

大量發布者送出事件,大量訂閱者依興趣收到——就像報紙訂閱:報社印新聞,訂閱者依興趣收報,中介負責把對的內容送給想要的人。

3
message queue(訊息佇列)

點對點——生產者把訊息投入佇列,消費者從佇列取出,或被通知有新訊息到達,提供生產者與消費者之間的一層間接。

4
tuple space(元組空間)

process 把結構化資料(tuple)放進一個持久的元組空間,其他 process 依樣式讀取或移除,讀寫雙方不必同時在線。

5
DSM(分散式共享記憶體)

讓不共用實體記憶體的 process,像讀寫本地變數一樣共享資料——把「共享記憶體」這個熟悉的寫法,包裝成一個抽象。

🎯
怎麼選?看你要哪種解耦

要把同一則訊息送給很多人 → group communication 或 publish-subscribe。一對一、可靠投遞、可暫存 → message queue。讀寫雙方不必同時在線 → tuple space。想用「讀寫共享變數」的熟悉寫法 → DSM。

小試身手

「誰在通訊」跟「怎麼通訊」,這一站的兩把鑰匙都拿到了。來兩題檢查一下:

一家公司想讓多個外部團隊各自開發模組、再放心地組裝在一起,最在意「沒有隱藏的相依性」。最適合的抽象是?
一個股市行情系統有大量發布者持續送出價格事件,給大量依興趣訂閱的消費者。最適合的間接通訊技術是?
🧭
下一站:角色與放置

知道了「誰在講話」,下一步是看這些角色怎麼分工、服務放在哪裡。往下捲。

03

角色與放置:Client-Server、P2P 與架構模式

同一份服務,擺在哪裡、由誰主導,決定了整個系統會不會卡住、會不會難以擴展

先問一句:誰主導、誰配合?

行程(或物件、元件、服務)互動時,會擔任不同的角色——而這些角色,就決定了整個系統的架構長什麼樣子。這一節,課本挑出兩種最重要的風格互相對照:client-server(主從)peer-to-peer(對等)

Client-server 是提到分散式系統時最常被舉的例子,歷史最悠久,至今也最廣泛被採用:client 行程向個別的 server 行程發出請求,去存取 server 管理的共享資源。而 server 自己也可能是別的 server 的 client——例如 web server 常是本地檔案 server 的 client,用來管理網頁檔案;web server 跟大部分網路服務也都是 DNS 服務的 client。

更有趣的是搜尋引擎:它一方面回應瀏覽器 client 的查詢(此時它是 server),一方面又派出 web crawler 去對別的 web server 發 HTTP 請求(此時它是 client)。這兩件事彼此獨立、不太需要同步,可以並行執行——同一個程式,同時活成兩種角色。

🍽️
先給你一個畫面:上餐廳點餐

Client-server 就像上餐廳:客人(client)點餐,廚房(server)做菜,角色分明、流程簡單明瞭。但所有客人都靠同一間廚房——客人一多,廚房就開始塞車。這正是 client-server 最大的隱憂:服務集中在單一位置,一旦超過那台機器與網路頻寬的容量,就卡住了。

直接讀原文,旁邊就是白話

這幾句是課本介紹 client-server 與 peer-to-peer 差異的原話。左邊原文、右邊白話導讀——先讀懂原文的氣口,再看整段在說什麼。

原文 · DSCD Ch.2 Client-server: client processes interact with individual server processes in potentially separate host computers in order to access the shared resources that they manage. Peer-to-peer: all of the processes involved in a task or activity play similar roles, interacting cooperatively as peers without any distinction between client and server processes. While the client-server model offers a direct and relatively simple approach to the sharing of data and other resources, it scales poorly. The key insight that led to the development of peer-to-peer systems is that the network and computing resources owned by the users of a service could also be put to use to support that service.
白話導讀

Client-server 的定義很直白:client 行程去找個別的 server 行程要東西,存取 server 管理的共享資源——雙方角色分得清清楚楚,可能還分別跑在不同的主機上。

Peer-to-peer 剛好相反:參與同一件任務的所有行程都扮演差不多的角色,彼此合作、地位對等,完全沒有 client 跟 server 的區分。

Client-server 的優點是直接又相對簡單,但擴展性很差——把服務集中放在單一位址,一旦超出那台機器和網路頻寬的承受量,就沒辦法再長大了。

P2P 的關鍵洞見,是把「使用者自己擁有」的運算與網路資源,也一起拿來支援服務——這樣一來,能用的資源量就會隨著使用者人數一起變多。

🔑
一句話記住兩種架構的分歧點

Client-server 把資源鎖進一個地址,換來簡單,卻也換來瓶頸;P2P 把資源攤開在每個使用者身上,換來成長性,卻也換來協調的複雜度。沒有誰絕對更好,只有「你在賭哪一邊」。

招牌互動:同一件事,兩種跑法

下面先示範 client-server 怎麼跑,再示範 P2P 怎麼跑。按「下一步」,感受一下「集中處理」跟「大家互相直接交換」有多不一樣。

💻
Client A
🗄️
Server(集中)
💻
Client B
⚙️
節點 P1
⚙️
節點 P2
⚙️
節點 P3
按「下一步」開始
🥘
P2P 像百樂餐(potluck)

每位賓客都帶一道菜來,同時也吃別人帶的菜——人人既是「供應者」也是「享用者」。來的人越多,桌上的菜反而越豐盛,這正是 P2P 最迷人的特性:資源隨參與者增加而成長。但百樂餐也比較亂:誰帶了什麼、東西放哪、要不要多帶一份備用(複製副本),協調起來遠比上餐廳複雜。

把兩種架構定格成一張對照表

動畫跑太快?這是靜態總結——兩種角色風格最核心的取捨。

🍽️
Client-Server

角色明確主從,直接又簡單。案例:Web、DNS、FTP、電子郵件。缺點:擴展性差——服務集中在單一位址,超過那台機器與網路頻寬的容量就卡住。

🥘
Peer-to-Peer

角色全部對等,資源隨使用者人數一起成長。案例:Napster、BitTorrent。缺點:複雜度高——物件被分散到大量電腦上,還要複製多份副本以分攤負載、應付斷線。

為什麼 P2P 會「複雜許多」?因為在 P2P 裡,大量資料物件被分散,每台電腦只存一小部分;每個物件還要複製(replicate)到好幾台,以分攤負載並在某台斷線時仍可用。要「放置物件、找回物件、維護副本」,自然比 client-server 複雜許多。

📇
Server 也能同時是 Client

別把 client-server 想成一條單向的路。Web server 是檔案 server 的 client;搜尋引擎既是 server(回應瀏覽器查詢),又是 client(它的 web crawler 去抓別的網站)。角色是相對的,看你站在哪一段互動裡。

P2P 的擴展瓶頸怎麼解?先談「放置」這件事

同樣的物件或服務,放在哪台機器、哪個行程,會大幅影響效能、可靠度與安全。放置沒有萬用公式,課本聚焦四種策略:

🖥️
多伺服器

用多個 server 行程合作提供服務,可分割(partition)物件分散管理(如 Web),或維持複製副本(如 Sun NIS 讓每台伺服器持有同一份密碼檔)。好處:分攤負載、提升可用性。

🧊
快取 Caching

快取是離某個 client(或一群 client)較近的資料存放區。要用先查快取、有最新副本就直接給;沒有才向原始 server 取得。好處:降低延遲與對外網路的負載。

📦
行動程式碼

行動程式碼(mobile code)如 applet,被下載到瀏覽器本地執行,互動反應快,不必每次都隔著網路等。好處:本地執行、可支援 server 主動 push。

🧑‍💼
行動代理

行動代理(mobile agent)帶著程式與資料親自跑到各個站點,在當地做許多次本地查詢,再帶結果回來。好處:把多次昂貴的遠端呼叫換成當地的本地呼叫。

行動程式碼像「外送食譜到你家」:你點連結,程式碼被下載到瀏覽器在本地執行;行動代理則像「派一位採購員出差」——帶著程式與資料親自跑到各站點比價、查詢,再帶結果回來。但這兩者都繞不開同一個共同主題:安全。行動程式碼可能危害本機資源,所以瀏覽器會限制 applet 對本地資源的存取;行動代理對它造訪的電腦也是威脅,接收方應依代理代表的使用者身分決定可用哪些本地資源,而且代理本身也可能因被拒存取而無法完成任務,因此適用範圍有限

🧊
快取像家裡的小冰箱

常喝的飲料先放小冰箱(離你近的快取),要喝時先看小冰箱有沒有、且還新鮮,有就直接拿;沒有才去大賣場(原始 server)補貨。Web 瀏覽器會用特別的 HTTP 請求,跟原始伺服器確認快取的頁面是不是還是最新的,再決定要不要直接顯示。

💡
Push 模型小知識

一般 Web 互動都由 client 發起(你點、你問,server 才答);若要 server 主動推播(例如股價更新),就需要先下載特別的程式碼來接收更新——這正是行動程式碼的另一種用法。

再拆一層:Layering 是垂直的,Tiering 是水平的

放置談的是「這個物件放哪台機器」,但整個系統還有更大的組織方式:分層(layering)把複雜系統切成數層——上層使用下層提供的服務,且上層不需知道下層怎麼實作。最底層是平台(platform)(硬體+作業系統),上面疊一層中介軟體(middleware),用來遮蔽異質性、提供方便的程式設計模型。

分層式架構(tiering)則與 layering 互補:layering 管垂直抽象,tiering 則是把某一層的功能切開、放到適當的伺服器與實體節點上。把應用拆成「呈現(presentation)」「應用(application)」「資料(data)」三塊邏輯後,就能決定要用二層還是三層。

二層(two-tier)
三層(three-tier)
Layering(垂直)
Tiering(水平)
點擊上方元件查看說明
🍰
蛋糕的比喻

Layering 像蛋糕一層疊一層地往上疊,上層吃下層的服務;tiering 則像把某一層的內餡拆開,分別放進不同的廚房(伺服器)去做。兩者談的是完全不同的維度,並不是互相取代的關係。

局部更新、瘦客戶端、以及 middleware 的極限

傳統 Web 要更新一小塊也得整頁重新請求,使用者只能乾等。AJAX像派一個小跑腿:瀏覽器非同步向 server 要一小塊資料,回來只更新該部分,其餘畫面照常可操作。Google Maps 拖地圖時即時補上新圖磚,就是經典例子。

瘦客戶端(thin client)把複雜度搬到網路端的服務,本地裝置只負責視窗式介面——好處是手機等簡單裝置也能用到強大服務;壞處是像 CAD、影像處理這類高互動圖形作業,因為要傳大量影像資料,延遲會令人難忍。VNC 把這個想法推到極致——協定只做一件原始的事:把一塊像素矩形畫到螢幕指定位置,因此能跨任何作業系統運作。

📮
Middleware 也有極限:end-to-end argument

有些與通訊相關的功能,只有站在通訊端點的應用程式自己才能完整可靠地實作——就像貴重包裹,就算快遞(通訊系統)有基本保障,真正關鍵的檢查只有寄收件人(端點應用)自己能完整做到。例如傳超大郵件,TCP 無法從重大網路中斷中恢復,於是郵件服務必須在應用層自己加一層容錯:記錄進度、用新連線續傳。這對 middleware 設計者是個兩難:不是所有通訊功能都能被抽象到 middleware 而與應用無關。

小試身手

把角色、放置、layering/tiering 串起來,你已經摸到「系統長什麼樣子」的骨架了。來兩題:

P2P 架構最關鍵的洞見是什麼?
使用快取時,為什麼通常要先「跟原始伺服器確認副本是否仍是最新」?
下一站:互動模型

角色與放置談的是「空間」怎麼分工——誰在哪、資源放哪台機器。接下來要談的是「時間」這件事有多不可靠:往下捲。

04

沒有全域時鐘:互動模型與同步/非同步

沒有一台電腦的時鐘會跟別人一樣快——這個看似小事的物理限制,決定了整個系統怎麼想「時間」

先講最實際的:訊息在路上要花多久、能塞多少、會不會忽快忽慢

分散式系統裡的行程(process)靠訊息互動,彼此的行為由分散式演算法描述——每個行程有自己完全私有的狀態,別的行程無法直接偷看。而互動模型要面對的第一個限制因素,是通訊效能常常是瓶頸,課本用三個量描述它:

latency(延遲)是訊息開始送出、到對方開始收到之間的時間;bandwidth(頻寬)是單位時間內網路能傳的總資訊量;jitter(抖動)則是一連串訊息送達時間的變異。

🛣️
用開車上高速公路理解這三量

latency 是從你家出發到抵達目的地要花的時間——即使路很寬,只要距離遠或塞在交流道,也得等。bandwidth 是這條路有幾線道,單位時間能讓多少車通過;車太多就得共用車道、互相排擠。jitter 則是一車隊抵達時間的忽快忽慢——對播音樂這種需要等間隔送達的場景,抖動會讓聲音斷斷續續、嚴重失真。

直接讀原文,旁邊就是白話

這幾句話幾乎是本節最核心的定義區塊。原文放左邊,白話導讀放右邊——先讀懂原文的氣口,再看整段在說什麼。

原文 · Distributed Systems Ch.2 The delay between the start of a message's transmission from one process and the beginning of its receipt by another is referred to as latency. The bandwidth of a computer network is the total amount of information that can be transmitted over it in a given time. Jitter is the variation in the time taken to deliver a series of messages. Computer clocks drift from perfect time and, more importantly, their drift rates differ from one another. Even if the clocks on all the computers in a distributed system are set to the same time initially, their clocks will eventually vary quite significantly unless corrections are applied.
白話翻譯

訊息從一個行程開始送出、到另一個行程開始收到之間的延遲,就叫 latency。

電腦網路的 bandwidth,是單位時間內這條網路能傳輸的總資訊量。

jitter 是一連串訊息送達時間的變異——忽快忽慢的程度。

電腦的時鐘會偏離完美時間,更麻煩的是,每台電腦的偏離速率還都不一樣。

就算一開始把所有電腦的時鐘都對到同一個時間,只要不持續校正,過一段時間它們還是會明顯地各說各話。

一群各走不準、且走不準程度都不同的手錶

這是時鐘漂移率(clock drift rate)的最佳畫面:每支錶走快走慢,且快慢程度彼此不同,就算一開始對好時間,過陣子也會差很多。這就是為什麼分散式系統維持不了單一的全域時間。

招牌互動:看三台電腦的時鐘各走各的

下面三台電腦一開始把時鐘校到完全一致。按「下一步」,看它們的時鐘怎麼各自漂移、又只能靠訊息互相估計時間——而不是真的「對到」。

🕐
電腦 A(有 GPS)
🕒
電腦 B(走快一點)
🕗
電腦 C(走慢一點)
按「下一步」開始
📡
為什麼不能每台都裝 GPS 校時?

用 GPS 接收器校時精度約 1 微秒,聽起來很準——但 GPS 訊號室內收不到,成本也不可能每台電腦都裝。改用「有準確時源的電腦發送計時訊息給別人」,結果又受「變動的訊息延遲」拖累,無法完美。所以結論很直白:全域時間終究不可能完美,這正是下一段兩種模型的起點。

既然對不準,那就老實面對:兩種對時間的態度

由於很難對行程執行、訊息傳遞、時鐘漂移設限,課本索性給出兩個極端模型,一個對時間有強假設,一個完全不假設。

Synchronous(同步)系統

三項都有已知界限:每個步驟的執行時間有已知上下界;每則訊息在已知有界時間內送達;每個行程的時鐘漂移率有已知界限。好處是可以用timeout(逾時)偵測行程失效;難處是很難給出保證得了的真實界限——界限若不可靠,設計就不可靠。

Asynchronous(非同步)系統

對執行速度、訊息延遲、時鐘漂移都不設任何界限。一步可能花一皮秒,也可能花一世紀;訊息可能瞬間到,也可能好幾年才到。這恰好描述了網際網路

⛰️
山頭上的協調難題:Pepperland

兩支軍隊 Apple 與 Orange 紮營在兩座山頭,靠信差穿越山谷約定何時一起衝鋒。非同步 Pepperland:信差速度變化極大,送「衝鋒!」可能 5 分鐘到,也可能 3 小時才到,沒人能保證時間,很難精準約好同時行動。同步 Pepperland:大家知道每則訊息至少 min、至多 max 分鐘會到——帶頭的送出「衝鋒!」後等 min 分鐘再衝,另一隊收到後等 1 分鐘再衝,就能保證在帶頭者之後、且不超過 (max − min + 1) 分鐘內跟上。

🔑
記住這句金句

凡對非同步系統有效的解法,對同步系統也有效——因為同步只是在非同步的基礎上多加了時間假設,假設更寬鬆的解法自然也適用在假設更多的情境。

動手配配看:這句話屬於同步系統,還是非同步系統?

把下面幾個特徵,拖到它該屬於的類別。配完按「對答案」。

每個步驟的執行時間有已知上下界
可以用 timeout 可靠地偵測行程失效
對執行速度、訊息延遲、時鐘漂移都不設任何界限
網際網路正是這種系統的真實寫照
同步系統(synchronous)
拖到這裡
非同步系統(asynchronous)
拖到這裡
⏱️
非同步系統裡,逾時證明不了「死了」

在非同步系統中,timeout 只能說明「這個行程目前沒有回應」——它可能當機了,也可能只是很慢,或者訊息還在路上晃。你分不清是壞了還是變慢,這正是後面失效模型要處理的麻煩。

既然時鐘靠不住,那怎麼排出事情發生的先後?

來看一個 email 例子:X 寄出主旨「Meeting」的信,Y、Z 各自回覆「Re: Meeting」。由於投遞延遲各自變動,某些使用者可能看到順序顛倒——先看到回覆,才看到原信。

如果時鐘能完美同步,每則訊息都可以帶上送出時間戳 t1 < t2 < t3 來排序。但時鐘無法完美同步,於是 Lamport(1978)提出logical time(邏輯時間):不靠時鐘,靠因果關係來排序。

📤
鐵律一:先送出、後收到

訊息一定是先被送出,才會被對方收到——這件事跟時鐘準不準完全無關,是邏輯上必然的順序。

↩️
鐵律二:先收到、後回覆

回覆一定是在收到原訊息之後才送出的。以 email 例子來說,Y 一定是先收到 X 的 m1,才送出回覆 m2。

邏輯時間把這些順序關係轉成編號——越晚發生的事件編號越大,就能在沒有準時鐘的情況下,推斷出合理的事件順序。

🧭
不看錶,看誰先導致誰

邏輯時間的精神:就算每個人的手錶都不準,我們仍然知道「先寄信才有人收信、收信後才會回覆」——靠這些因果關係,一樣能排出讓人信服的先後順序。

小試身手

時間不可靠、時鐘各走各的——這是本節最核心的物理限制。來兩題檢查一下:

為什麼分散式系統中無法維持單一的全域時間?
為什麼在同步系統中可以用 timeout 來偵測行程失效,但在非同步系統中卻不可靠?
🛡️
下一站:失效與安全模型

時間不可靠之後,最後要面對的是:東西會壞、也會有人蓄意搞破壞。往下捲。

05

會壞在哪裡、會被誰盯上:失效模型與安全模型

東西會壞、人會使壞——先把「壞的方式」分類清楚,才知道怎麼防

系統會壞,但「怎麼壞」有分類

在分散式系統裡,行程(process)與通訊通道都可能失效(failure)——偏離了正確或期望的行為。光說「壞了」沒有用,我們需要一套失效模型(failure model),把「壞的方式」講清楚,這樣才能分析它的影響,進而設計出扛得住這種壞法的系統。

課本引用 Hadzilacos 與 Toueg 的分類法,把行程與通訊通道的失效分成三大類:遺漏失效(omission failures)任意失效(arbitrary / Byzantine failures)時序失效(timing failures)。這套分類會貫穿全書——後面章節談可靠通訊協定、談交易的兩階段提交,都是在回答「面對這些已知的壞法,我該怎麼設計」。

🧩
先把「壞」分類,才能對症下藥

就像醫生看診不會只寫「不舒服」,而要分「發炎、感染、外傷」——工程師面對系統故障,也得先分清楚是「該做的沒做」(遺漏)、還是「做了但亂做」(任意),防禦手段完全不同。

直接讀原文,旁邊就是白話

這幾句話是課本對遺漏失效與任意失效最精準的定義。原文放左邊,白話導讀放右邊。

原文 · DSCD Ch.2 The faults classified as omission failures refer to cases when a process or communication channel fails to perform actions that it is supposed to do. When we say that a process has crashed we mean that it has halted and will not execute any further steps of its program ever. A process crash is called fail-stop if other processes can detect certainly that the process has crashed. The term arbitrary or Byzantine failure is used to describe the worst possible failure semantics, in which any type of error may occur. Arbitrary failures in processes cannot be detected by seeing whether the process responds to invocations, because it might arbitrarily omit to reply.
白話翻譯

被歸類為遺漏失效的錯誤,指的是行程或通訊通道「該做的動作沒做」的情況。

當我們說一個行程「當機」了,意思是它已經停住,再也不會執行程式裡的任何後續步驟。

如果其他行程能「確定地」偵測到某個行程已經當機,這種當機就叫做 fail-stop。

任意失效(或稱 Byzantine 失效)這個詞,用來描述最糟糕的失效語意——任何類型的錯誤都可能發生。

行程的任意失效沒辦法靠「它有沒有回應請求」來偵測,因為它可能就是任意地選擇不回覆。

🔑
「偵測不到」才是最麻煩的地方

一般 crash 靠 timeout(逾時)去猜對方是不是壞了,但在非同步系統裡,timeout 只能告訴你「對方沒回應」,卻不能告訴你他是當機了、變慢了,還是訊息根本還在路上。

把「壞的方式」定格成三大類

課本用員工來比喻這三種失效,非常好記:

1
遺漏失效(omission)= 突然消失的員工

行程的遺漏失效主要是crash(當機):本來該交報告卻人間蒸發。若公司有打卡系統(同步系統+保證訊息送達的 timeout),大家能確定他沒來,這就是 fail-stop;若沒有這套機制,你只知道他沒回訊息,卻不確定是請假、塞車還是真的當了。通訊通道也會遺漏失效——訊息在半路被丟掉(dropping messages),再細分為 send-omission、receive-omission、channel-omission。

2
任意失效(Byzantine)= 最糟糕的員工

他可能交假報告、亂傳訊息、甚至裝沒事其實什麼都沒做——回傳錯誤的值、該做的不做、不該做的亂做。你無法靠「他有沒有回應」判斷,因為他可能故意亂回。通道的任意失效(內容被竄改、送出不存在的訊息、重複投遞)在現實中很罕見,因為通訊軟體早就用 checksum 與序號把這類錯誤攔下來了。

3
時序失效(timing)= 慢吞吞的員工

只在同步系統裡才談得上——執行、傳遞或時鐘漂移超過了事先設定的界限。只有你事先約定了截止時間,才能說他「遲交=時序失效」;若你根本沒設期限(非同步系統),他再慢你也不能說他失效。

⚠️
大部分失效其實是「溫和」的

課本特別指出:失效可以依嚴重程度分級,前面談的遺漏失效、時序失效、效能失效都屬於良性失效(benign failures),而且分散式系統裡大多數失效都是良性的——真正棘手、防不勝防的任意失效,反而是少數。

招牌互動:這個情境屬於哪種失效?

把下面三個失效情境,拖到它對應的失效類別上。配完按「對答案」。

訊息在半路被丟掉,根本沒送到收方的訊息緩衝區
伺服器直接當機,之後再也不會執行任何後續步驟
收到一則被竄改過的假訊息,內容跟原本送出的完全不同
遺漏失效(omission)——通道該做的傳輸動作沒做到
拖到這裡
遺漏失效(omission)——行程的當機(crash)
拖到這裡
任意失效(arbitrary / Byzantine)——內容被破壞或偽造
拖到這裡
🛠️
實用超能力:遮蔽(masking)

每個元件都由其他元件組成,因此可以用較不可靠的元件建出較可靠的服務——這就是遮蔽。例如 checksum 把「內容被破壞」這種任意失效,轉成「丟棄該訊息」的遺漏失效;再用重傳把遺漏失效藏起來——一步步把最壞情況,馴服成看起來一切正常。

失效模型防「壞掉」,安全模型防「使壞」

失效模型處理的是意外——東西自然壞掉。但分散式系統還要面對另一種威脅:有人故意搞破壞安全模型建立在架構模型之上:要確保分散式系統安全,就要保護行程、保護它們互動用的通道、並保護它們封裝的物件,不被未授權存取。

伺服器替使用者管理一堆物件,使用者透過 client 送出invocation,要伺服器對物件做操作。不同物件給不同人用,因此要用access right(存取權)規定誰能對某物件做哪些操作。而擁有這份存取權、下命令的權威,就叫principal(當事人)——可以是使用者,也可以是行程。

🕵️
先假想最壞的敵人

為了分析威脅,課本假設一個enemy(敵人/對手)——它能對任何行程送任何訊息,也能讀取或複製任兩個行程之間的任何訊息。就像郵差路線上有個壞人,能偷看每封信、也能冒名寄信。這種假設不是說現實一定有這麼強的敵人,而是「假設最壞情況,防禦才不會留破口」。

敵人能幹什麼壞事:對行程 vs 對通道

假設好了敵人的能力,課本接著把威脅拆成兩個對象:行程通訊通道

A
對行程的威脅:來源不可信

伺服器可能同時收到來自許多不同 client 的 invocation,光看請求本身,它沒辦法確定這一次請求背後真正的 principal 是誰——來源位址可以被偽造。反過來,client 也可能收到冒牌伺服器(spoofing)送來的假結果,卻以為是真的。

B
對通道的威脅:竊聽、竄改、注入、重放

敵人可以在訊息穿越網路與中間的閘道時,複製、竄改或注入訊息。另一種手法是把攔截到的舊訊息存下來,之後再重複送出,讓同一則訊息被一次又一次地重複利用——這就是重放攻擊(replay attack)

💸
重放攻擊:把轉帳單影印重送

這正是重放攻擊的經典例子——敵人存下一筆轉帳請求,重複送出就能一再得利。安全通道要靠時間戳才能擋住這種手法。

招牌互動:把「安全通道」一步步建起來

面對敵人竊聽、竄改的威脅,課本教的防禦是一層層疊上去的:先靠密碼學與共享祕密加密(encryption),再做認證(authentication),最後疊出一條安全通道(secure channel)。點點看下面每個節點:

😈 敵人竊聽/竄改的威脅
🔐 加密+認證
✅ 安全送達(secure channel)
點擊上方元件查看說明
📮
安全通道 = 防偽封條 + 掛號 + 時間戳的郵筒

雙方確知彼此身分(不會被冒名)、內容防偷防改(隱私與完整性)、每封都有時間戳(防重放)——三個性質缺一不可,正是安全通道的完整定義。

還有兩種威脅,最後小試身手

除了竊聽與竄改,課本還點名兩種威脅:denial of service(阻斷服務)——用大量無謂請求灌爆資源,讓正常使用者用不了;以及mobile code(行動程式碼)——接收並執行外來程式碼,可能是木馬。

💰
安全不是免費的

加密、認證、安全通道都有成本,所以實務上要先做threat model(威脅模型),盤點所有攻擊面,再權衡防禦的效益與成本——不是所有系統都要把每一道防線都拉滿。

某行程當機了,而且其他行程能「確定地」偵測到它已經當機。這屬於哪一種失效?
敵人把一筆「轉帳請求」的舊訊息存起來,事後重複送出以佔便宜。這是哪種攻擊,安全通道用什麼防它?
🗺️
本章總結:從「怎麼描述系統」到「怎麼防它出事」

這一章從物理模型的「一堆各異的電腦、靠不太準的網路連著」出發,走到架構模型的用戶端-伺服器與各種互動樣式,再到互動模型裡「同步 vs 非同步」這條分水嶺,最後停在這裡:失效模型告訴你系統會怎麼自然地壞掉——遺漏、任意、時序;安全模型告訴你系統會怎麼被人故意弄壞——敵人竊聽竄改、重放,而加密、認證、安全通道就是你的防線。這五個模型合起來,就是描述、分析、設計任何分散式系統的一整套語言。

📚
這一站,也是整章的終點

從物理模型的硬體差異,到架構模型的分工方式,到互動模型的時間假設,再到今天的失效與安全——你已經走完了描述一個分散式系統所需的完整骨架。這套骨架會在後面每一章反覆被用到:不管談的是通訊協定、複製、交易,最終都繞不開「這個系統長什麼樣、會怎麼壞、會被誰盯上」這三個問題。準備好,翻到下一章,繼續往下深挖分散式系統的設計細節。