計算機的時鐘(三):向量時鐘

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本系列文章主要介紹計算機系統中時鐘的處理。主要內容包含NTP,Lamport邏輯時鐘,向量時鐘,TrueTime等。本文是第三篇,介紹向量時鐘。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在"},{"type":"link","attrs":{"href":"http://yang.observer/2020/07/26/time-lamport-logical-time/","title":null},"content":[{"type":"text","text":"《計算機的時鐘(二):Lamport邏輯時鐘》"}]},{"type":"text","text":"中,我們介紹過"},{"type":"text","marks":[{"type":"strong"}],"text":"對於任意兩個事件a和b,如果 a → b,那麼 C (a) < C (b),但是反向並不成立,C(a) < C(b)推不出來a→b。"},{"type":"text","text":"本文介紹的向量時鐘(Vector Clocks)可以保證反向也能成立,也即充分條件變成了充分必要條件,這是如何做到的呢,且聽我一一道來。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"向量時鐘算法"},{"type":"link","attrs":{"href":"http://yang.observer/2020/09/12/vector-clock/#%E5%90%91%E9%87%8F%E6%97%B6%E9%92%9F%E7%AE%97%E6%B3%95","title":null}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘是1988年由Colin Fidge和Friedemann Mattern提出的,比Lamport老爺子提出邏輯時鐘晚了剛好十年。Lamport邏輯時鐘存在兩個問題,一個是上面說的C(a) < C(b)不能推導出a → b,這樣導致即使知道了兩個邏輯時鐘值,但卻不能確定這兩個事件的因果關係。第二個問題是進程“看到的”事件發生順序可能是錯的。舉個例子:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ab/abfcc05787784ba084ff672f1fc38a7b.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖一中,a事件發生於c之前,但是由於網絡延遲,P2先收到c事件再收到a事件,導致從P2的視角看先發生c事件再發生a事件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘可以解決這兩個問題,它的思想是進程間通信的時候,不光同步本進程的時鐘值,還同步自己知道的其他進程的時鐘值。算法如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分佈式系統中每個進程Pi保存一個本地邏輯時鐘向量值VCi,向量的長度是分佈式系統中進程的總個數。VCi (j) 表示進程Pi知道的進程Pj的本地邏輯時鐘值,VCi的更新算法如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"初始化VCi的值全爲0:VCi = [0, … , 0]"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"進程Pi每發生一次事件,VCi[i]加1。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"進程Pi給進程Pj發送消息,需要帶上自己的向量時鐘VCi。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"進程Pj接收消息,需要做兩步操作。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘舉例:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c1/c1f354c5afe46a60d9960d95e57f31af.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘裏的向量是一種偏序關係:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果向量VCi中的每個元素VCi[k]都小於等於VCj中的對應元素VCj[k],則VCi "},{"type":"text","marks":[{"type":"italic"}],"text":"≤"},{"type":"text","text":" VCj。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果VCi中的每個元素VCi[k]都和VCj中的對應元素VCj[k]相等,則VCi = VCj。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果VCi和VCj不能比較大小,則稱兩個向量是併發的 VCi || VCj。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從以上算法可以很容易地得出下面兩個結論:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"同一個進程內的兩個事件a和b,如果 a → b,那麼 VCi (a) < VCi (b)。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"a是Pi進程的消息發送事件,b是Pj進程該消息的接收事件,那麼 VCi (a) < VCj (b)。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由以上兩個結論又可以得出,"},{"type":"text","marks":[{"type":"strong"}],"text":"對於任意兩個事件a和b,如果 a → b,那麼 VC (a) < VC (b)"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼證明VC(a) < VC(b) 可以推導a → b呢?(以下證明過程摘自"},{"type":"link","attrs":{"href":"https://writings.sh/post/logical-clocks","title":null},"content":[{"type":"text","text":"邏輯時鐘 - 如何刻畫分佈式中的事件順序"}]},{"type":"text","text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果事件a和b在同一個進程內,很顯然 a → b。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果事件a和b在不同進程內,比如Pa和Pb。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"設VCa = [m ,n], VCb = [s, t]。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲VCa < VCb,所以m "},{"type":"text","marks":[{"type":"italic"}],"text":"≤"},{"type":"text","text":" s,所以必然在不早於a之前和不晚於b之後的時間內,Pa向Pb發送了消息,否則Pb對Pa的計數器得不到及時刷新,s就不會小於m。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/53/53c66c03a1a9e622306e1128c3efa2be.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際上,可以分爲以下幾種情況:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/82/822212f58663a081a7294253be97ce6e.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"當a = c且d = b,易得a → b。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"當a = c且d → b,由傳遞性,得a → b。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"同樣對於d = b且a → c的情況。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"當a → c且d → b,根據進程內的算法邏輯性和傳遞性,也很容易得出結論。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"綜上: VCa < VCb 推導出 a → b 得證。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘將Lamport邏輯時鐘的全序時鐘值改成了向量時鐘的偏序關係,可以準確刻畫事件的順序,"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"因果關係與光錐"},{"type":"link","attrs":{"href":"http://yang.observer/2020/09/12/vector-clock/#%E5%9B%A0%E6%9E%9C%E5%85%B3%E7%B3%BB%E4%B8%8E%E5%85%89%E9%94%A5","title":null}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘可以反映事件之間的因果關係,下圖中對於中間的B4事件,左邊藍色區域內的事件都是B4事件的“因”,右邊紅色區域內的事件都是B4事件的“果”。而上下白色區域內的事件則屬於和B4事件沒有因果關係的平行事件。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8e/8eceaa63e61946c20c47f1b12ab6e214.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這讓我想起了相對論中的"},{"type":"link","attrs":{"href":"https://zh.wikipedia.org/wiki/%E5%85%89%E9%94%A5","title":null},"content":[{"type":"text","text":"光錐"}]},{"type":"text","text":"。光錐是"},{"type":"link","attrs":{"href":"https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA","title":null},"content":[{"type":"text","text":"閔可夫斯基時空"}]},{"type":"text","text":"下能夠與一個單一事件通過光速存在因果聯繫的所有點的集合,簡單地說就是事件所能影響的時空範圍,它的圖形如下:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/19/19942ef0921fbc5ca2bf9d0d6b81ad44.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"時空是由三維空間和一維時間構成的,由於人類是三維空間中的生物,沒辦法感受四維時空,所以光錐圖中把三維的空間簡化爲了二維xy平面,時間是z軸。空間平面中的每一個維度都可以向正負兩個方向移動,而時間不可能倒退,只能向正方向移動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以當前觀測者爲原點,因爲任何物體的運動速度都不可能超過光速,所以它產生的事件造成的影響也不可能超過光速。這個事件每秒鐘在二維空間平面中的傳播範圍也不可能超過光每秒鐘走過的地方。所以光錐呈現一個圓錐的形狀。光錐分爲未來光錐和過去光錐,未來光錐指當前發生的事件對未來造成影響的範圍,而過去光錐指過去多大時空範圍的事件能對現在造成影響。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cb/cbc90cdc58c2270b8e216d7dd4cac6af.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上圖中,把當前時刻的太陽作爲光錐的座標原點,因爲太陽光到地球需要8分鐘,所以當前時刻太陽發出的光需要8分鐘後才能對地球造成影響。這就是未來光錐,也就是當前時刻的事件對未來造成影響的範圍。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4b/4be90119f344ff21b8e150e4cb5213fb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果把當前時刻的地球作爲光錐的座標原點,那麼只有8分鐘之前的太陽光纔會對地球造成影響,8分鐘前的太陽處於過去光錐的範圍內。而4分鐘前的太陽不會對現在的地球造成影響,它處在過去光錐之外。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"“宇宙中的任何事件都只能影響它的將來光錐內的物體,凡事在事件的將來光錐外的物體不會受該事件的任何影響。”"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"向量時鐘的應用"},{"type":"link","attrs":{"href":"http://yang.observer/2020/09/12/vector-clock/#%E5%90%91%E9%87%8F%E6%97%B6%E9%92%9F%E7%9A%84%E5%BA%94%E7%94%A8","title":null}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向量時鐘有什麼作用呢?舉兩個使用例子。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作用之一是檢測數據衝突。分佈式數據庫中數據存在多個副本,每個副本都可能提供寫操作,如果兩個副本都對同一個數據進行寫操作,就可能造成衝突,向量時鐘可以檢測這種衝突,但不能解決衝突。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4c/4c15cb250990b459351729a4262dc27d.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上圖中 a → b → c → d → e 都有因果關係,不會產生衝突,但是e和f是併發關係 e || f,這兩個會有數據衝突,向量時鐘可以檢測這種衝突,但是需要應用層來解決衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作用之二是確定事件間的因果關係。舉個微信朋友圈的例子。微信朋友圈不同地域的用戶可能在不同的服務器上,通過網絡消息來同步朋友圈好友發的圖片以及對應的評論。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ec/eca881ed73e210e27c3f25ec8dee7f8f.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上海小王發了一個風景圖片到朋友圈,香港Mary看到後評論了問“這是哪”,上海小王回覆評論“梅里雪山”。由於網絡原因,對評論的回覆先到了加拿大的服務器,評論後到,導致加拿大Kate先看到回答“梅里雪山”,後看到提問“這是哪”。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6b/6b12d27efa6f8210a4347089d6a7b43e.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用向量時鐘,VC(c) < VC(e),因此 c → e,加拿大的服務器知道c發生在e前面,可以對評論和回覆正確排序後顯示。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"參考"},{"type":"link","attrs":{"href":"http://yang.observer/2020/09/12/vector-clock/#%E5%8F%82%E8%80%83","title":null}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://www2.imm.dtu.dk/courses/02220/2015/L7/Logical_Time.pdf","title":null},"content":[{"type":"text","text":"Logical Time"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Vector_clock","title":null},"content":[{"type":"text","text":"Vector Clock"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://zoo.cs.yale.edu/classes/cs426/2012/lab/bib/fidge88timestamps.pdf","title":null},"content":[{"type":"text","text":"Timestamps in Message-Passing Systems That Preserve the Partial Ordering"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://writings.sh/post/logical-clocks","title":null},"content":[{"type":"text","text":"邏輯時鐘 - 如何刻畫分佈式中的事件順序"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章