概念地圖・Lamport 邏輯時鐘
分類:系統
這一頁不只是把一個概念解釋一遍——一張自己畫的結構圖,加上拿台灣情境從頭走一次的實例演練、這個框架什麼時候會騙你,以及它接回 P.A.I.N. 之後長什麼樣。一頁必須交付的三層 →
Lamport 邏輯時鐘:三台機器的錶不同步,照樣排得出先後
三台電腦的錶各走各的,差幾十秒是常態。Lamport 邏輯時鐘乾脆不修錶——它給每個行程一個從零起算的計數器,本地做一件事就加一,送訊息時把自己的號碼一起送出去,收到訊息就取兩邊較大的那個再加一。畫出來是幾條垂直的時間線,線上是帶號碼的事件,跨線的斜箭頭是訊息。這張圖不回答哪件事幾點幾分發生,它只回答一件事:有沒有一條由訊息串起來的路,把 A 接到 B。有那條路,號碼一定由小到大。
三條線上的數字怎麼長出來
八個事件,八個號碼,每一個都能拿規則代回去驗一次。
| 事件 | 哪條線 | 怎麼算出來 | 這個號碼說了什麼 |
|---|---|---|---|
| a = 1 | P1 | 本地事件,0 加一 | 這條線的第一筆 |
| b = 2 | P1 | 本地事件,1 加一;訊息帶著 2 出發 | 送出的那一刻被記下來 |
| c = 1 | P2 | 本地事件,0 加一 | 跟 a 同號,兩者之間沒有箭頭 |
| d = 3 | P2 | 收到 b:max(1,2)+ 1 = 3 | 一定晚於 b |
| e = 4 | P2 | 本地事件,3 加一;訊息帶著 4 出發 | 承接 d 的那條因果 |
| f = 1 | P3 | 本地事件,0 加一 | 這條線的第一筆 |
| g = 2 | P3 | 本地事件,1 加一 | 跟 b 同號,兩者之間沒有箭頭 |
| h = 5 | P3 | 收到 e:max(2,4)+ 1 = 5 | 這條因果鏈的終點 |
把有箭頭連著的那一串抽出來:a 的 1、b 的 2、d 的 3、e 的 4、h 的 5,五個號碼一路往上,中間沒有一次持平。這條由小到大是規則逼出來的——收到訊息時強制取大再加一,號碼在這條路上就不可能倒著走。而 a 與 c 都是 1、b 與 g 都是 2,這兩組之間一條箭頭都沒有;表格最後一欄把它們框成警示,因為這張圖對它們沒有答案。
你的紀錄能不能判先後,比對四個欄位
先別急著寫程式。拿你手上那幾份跨系統的單據,一欄一欄比對過去。
一、每一筆紀錄有沒有帶「它是被誰引發的」。出貨單、報關檔、進倉紀錄,多半只寫了誰、什麼時候、做了什麼。邏輯時鐘要的是第四欄:這一筆是收到哪一份文件才生出來的。缺了那一欄,號碼就只是流水號,排不出任何因果——它會照系統自己的節奏往上加,跟另一台機器上發生的事毫無關係。自問:翻開昨天那筆進倉紀錄,看得出它是被哪一份放行通知觸發的嗎?
二、系統之間有沒有真的傳訊息。兩套系統都連著同一個資料庫、卻從不互相通知,這種情況邏輯時鐘完全使不上力——它的號碼只在訊息真的流過的地方才長得出關係。報關行把放行通知推給倉庫,那是訊息;倉庫自己去掃描條碼,那是本地事件。兩者在圖上一個有箭頭、一個沒有,判得出來的東西差很多。自問:這兩套系統之間,一天有幾次是真的把一份文件交到對方手上?
三、同一個號碼會不會出現在兩件無關的事上。會,而且很常。倉庫盤點那一筆是 2、報關行收單那一筆也是 2,兩件事誰先誰後這套機制不回答。麻煩的是下游:把邏輯時鐘的號碼拿去當排序鍵丟進報表,同號的那幾筆會被資料庫用主鍵、用字母序悄悄排出一個順序——那個順序是資料庫編的。自問:你的報表遇到同號時,現在是誰在決定先後?
四、你要判的是先後,還是同時。爭議如果是「放行有沒有排在進倉之前」,這套號碼夠用。爭議如果是「這兩件事差了幾秒」「有沒有踩在同一分鐘裡」,它一個字都答不出來——它連秒這個單位都沒有。動手之前先把爭議的問句寫下來,看那個問句要的是順序,還是要一段長度。自問:這次爭議真正要的答案,用得到「幾點幾分」嗎?
一座保稅倉的三套系統,把爭議排一次
底下這座台灣中部的保稅倉,是為了把這個結構講清楚而編出來的示意情境,沒有指涉任何真實公司。
- 牆鐘上的三個時間:貨主的 ERP 寫 09:12 出貨、報關行寫 09:13 放行、保稅倉的 WMS 寫 09:14 進倉。三台機器的錶各有偏差,而偏差是多少沒有人量過——上次校時只知道這三台之間最多差到 90 秒。偏差沒人量過
- 60 秒撐不住 90 秒:放行與進倉在牆鐘上只隔 60 秒,而可能的偏差區間比這個間隔還大。把 90 秒往任一邊挪,兩件事的順序就翻面——牆鐘給的是「大概」。這一題牆鐘判不出來
- ERP 這一端:建出貨單 = 1,把出貨單送給報關行,號碼 1 跟著單子一起走。送出時不必等對方回話
- 報關行這一端:收到出貨單 = max(0,1)+ 1 = 2;建報關申請 = 3;把放行通知送給 WMS,帶著 3。放行掛在號碼 3 上
- 保稅倉 WMS 這一端:理貨掃描 = 1、盤點 = 2 是自己的本地事件;收到放行通知 = max(2,3)+ 1 = 4;登錄進倉 = 5。進倉掛在號碼 5 上
- 爭議的那一半結案了:放行是 3、進倉是 5,中間有一條訊息箭頭連著,所以放行一定排在進倉之前——不必問任何一台機器現在幾點。三台錶都不必準
- 另一半沒有結案:WMS 的盤點是 2,報關行收到出貨單那一筆也是 2,兩者之間一封訊息都沒有往來。誰先誰後,這套號碼交白卷。同號=無解
這場爭議被切成兩半。有訊息連著的那一半,號碼 3 與 5 把它結掉了,而且結得比牆鐘乾淨——不必知道哪一台機器的錶偏了幾秒,也不必假設那天 NTP 有沒有跑成功。沒有訊息連著的那一半,兩個 2 撞在一起,這套機制誠實地承認自己答不出來。真正該帶走的接縫在這裡:先確認你要判的那兩件事之間,到底有沒有一份文件真的從 A 交到了 B。有,號碼就夠用;沒有,換再精密的錶也只是把猜測換一個小數點。台灣的跨關區流程常常是三套系統各自對時、各自留紀錄,而那條「文件真的交過去」的路,往往才是最該補的一段。以上為說明結構用的示意情境,僅供理解框架之用。
這種時間戳什麼時候會騙你
- 號碼小,推不出它導致了另一件事。這個方向要單獨講一次:a 是 1、g 是 2,數字上 a 比較小,但兩者之間沒有任何訊息路徑,a 影響 g 的可能是零。這套機制保證的只有一個方向——有因果的一定由小到大;倒過來從「號碼比較小」讀出「它是原因」,那是讀圖的人自己加上去的。要把「同號或無關」跟「真的有先後」分開,得換一套會記住每條線各走到哪一格的機制,那正是向量時鐘接手的地方。
- 把號碼當時間軸畫圖,會畫出假的間隔。號碼 3 到號碼 5 之間,不代表兩件事隔了兩個單位的時間;中間可能是三毫秒,也可能是三小時。有人把邏輯時鐘的號碼直接當 x 軸做成折線圖,看起來事件均勻分佈,其實那條橫軸沒有任何物理意義——它只是計數器的刻度。要看時間長度就回頭讀牆鐘,兩種鐘各管各的事,別把它們畫進同一條軸。
- 只有一部分系統掛上規則,號碼會靜靜地失去意義。三套系統裡有兩套照規則加號碼、第三套沒有,那第三套送出的訊息不帶戳,收方就沒得取大——它會退回成「自己加一」,於是一條真實的因果鏈在圖上斷掉,而畫面上完全看不出來。上線這套機制前該先盤一份清單:哪些介面會真的傳訊息,其中有幾個是別人家的系統、你根本改不動。改不動的那幾條,就是圖上會斷的地方。
兩件事沒有箭頭連著的時候
三台電腦的錶各走各的,順序卻靠訊息自己帶著走。
這正是它最好用、也最容易被讀歪的地方。P.A.I.N. 的第一個字母問「誰在痛」,而邏輯時鐘的號碼只認一件事:有沒有一份東西真的從 A 交到了 B。放行是 3、進倉是 5,這兩個號碼把流程的骨架排得乾乾淨淨,卻沒有交代任何人為此損失了什麼。真正付代價的,是那個站在櫃檯前、被兩份互相矛盾的紀錄卡住的貨主——他的痛,一個號碼裡放不下。這張圖畫得出兩筆紀錄之間有沒有一條訊息串起來,畫不出那條訊息晚到的三十分鐘裡,誰在打電話、誰在賠倉租。所以拿它去做事的順序長這樣:先用號碼把爭議縮小到有答案的那一半,剩下那一半交回去給人問。今晚可以做的小動作只有一個——打開你手上任兩套系統,把它們之間真的會傳訊息的那個介面找出來,在紙上畫成一條箭頭。那條箭頭畫成之後,才輪到號碼上場。
關於邏輯時鐘,常被問到的幾件事
邏輯時鐘跟 NTP 校時是同一件事嗎?
兩者解的問題不同。NTP 想讓每台機器的錶盡量貼近真實時間,剩下的誤差通常落在幾毫秒到幾十毫秒,跨機房或校時失敗時可以拉到幾秒甚至更久。邏輯時鐘不管真實時間,它只發號碼,保證有因果關係的事件號碼由小到大。實務上兩個都要留:牆鐘給人看、給稽核用,號碼給程式判順序用。保稅倉那個例子的關鍵就在這裡——當偏差區間比兩件事的間隔還大,牆鐘判不出來,號碼可以。
計數器要從 0 還是從 1 開始?
從 0 起算,第一筆本地事件加一之後變成 1。這件事看起來只是慣例,代進「收到訊息」那條規則就會發現它有用:一個還沒發生過任何事的行程收到帶著 1 的訊息,算出來是 max(0,1)+ 1 = 2,比送出方的 1 大,順序成立。若計數器改成從 1 起算,第一筆本地事件會是 2,整條線往上平移一格,結論不變,但你跟同事對帳時看到的每個號碼都會差一。整個系統挑一種、寫進文件,比挑哪一種重要。
兩件事號碼一樣,到底能不能排先後?
這套機制不回答。號碼相同代表它們在各自的線上剛好走到同一格,而彼此之間沒有任何訊息路徑——在 Lamport 的定義裡,這兩件事叫「並行」。硬要排的話,常見做法是拿行程編號當第二把鑰匙(號碼一樣就比 P1、P2、P3),排出來的全序不會自相矛盾,但那只是為了讓程式有個決定,現實世界的先後仍然無從得知。要真的分辨並行與有先後,得改用向量時鐘:每個行程各帶一組數字,記住自己看過每條線走到哪一格。
導入這套規則,要改多少東西?
改動集中在兩個地方:每一筆紀錄多存一個整數欄位,以及每一個跨系統的訊息多帶一個整數。真正卡住的多半在那些你改不動的介面——對方的 ERP、報關行的舊系統、第三方物流的 API。只要鏈路上有一段不帶戳,那一段的因果就會斷,而斷點在畫面上沒有紅字。務實的做法是先挑一條真的常出爭議的鏈路,例如出貨到進倉這一段,只在這條路上把號碼跑通,跑順了再往外長。
三個數字排出來以後,那場爭議只剩一半。另一半——同號的那兩筆、還有那些從來沒互相傳過訊息的系統——得換別的工具接手。把事件貼成一條時間線再一起讀,是事件風暴那一套的強項;而訊息在哪些節點之間跑得通、哪些跑不通,先看巴倫網路拓撲畫的那三種連法。
喜歡這篇文章嗎?
每週幫你拆二本好書,把判斷力、好書金句、好問題,直送你的信箱。
不適合你可隨時退訂 · 每週兩封,陪你把書讀進生活。
送出即表示同意我們依隱私權政策使用你的 email。