分佈式系統概念與設計-第十四章筆記


時鐘和狀態管理
關於時鐘
1. 同步物理時鐘的算法 (Physical Clock)
2. 邏輯時鐘(Logic Clock),包括Vector Clock,用來ordering event,即使不知道事件發生的絕對時間

分佈式系統裏面,關於時鐘的問題,主要是沒有一個Global Physical Time (因爲每個系統都有自己的physical clock)
這帶來的一個問題就是對於狀態的管理,無法確切的得知某個process的state(因爲無法依靠時間來判斷,但是不是應該通過消息來trigger麼?)

例子
一組process,跑在各自的processor上面,各個processor之間沒有share memory
每個process P都有自己的狀態S,隨着process的running,狀態會自己變化
這裏,S是個抽象的概念,包含process裏面相關的一組變量值,甚至包括文件
process之間只能通過消息通信
每個process都有自己的action,例如消息的send 、receive,or some operation that changes the state
在實際應用中,這裏的action會比較“高大上”,例如client dispatched order message’ or ‘merchant server recorded transaction to log
每當上面提到的某個action發生的時候,我們說有一個Event發生了
event之間是有順序關係的,並且

關於PC 物理時鐘的管理
最底層,叫physical clock,實際是電子裝置(芯片?)electronic device,數晶振的震盪次數count oscillations occurring in a crystal at a definite frequency,然後存到couter register裏面 H(t)
然後到OS這一層,從寄存器裏面取出H(t),弄個算法,變成process可讀的時間C(t) = aH(t) + b
For example, C(t) could be the 64-bit value of the number of nanoseconds that have elapsed at time t since a convenient reference time.
這就是“時間”在OS裏面的具體存儲形式,例如,通常好像是從1900年到現在的納秒數值

爲什麼網絡上面的Server不能保持一致的時間
主要就是因爲各個server上面晶振的頻率不能保持一致,一方面是硬件造成的,另外一方面,即使是同一個晶振,溫度不同,頻率也會有變化,所以count的時候就不準了。
晶振的工業誤差,10的-6次方秒/沒秒 => 每產生1s的誤差,需要100000S(11.6天)

所以,server需要經常採用外部時鐘來同步自己 => 最準的就是原子鐘誤差是10的13次方分之一,known as International Atomic Time
實踐中,通常各種設備是通過UTC來矯正自己的時間,UTC是base在原子鐘上面的,並且引入了“閏秒”的概念,來做定期的矯正 => 來keep it in step withastronomical time(應該是真實的地球自轉的真實時間=> 地球自轉越來越慢)
UTC,通過radio或者衛星給的GPS送達各個設備
UTC signals are synchronized and broadcast regularly from landbased radio stations and satellites (GPS) covering many parts of the world.

上面扯了一堆時鐘的原理,總算進正題說同步了
兩種
External Sync:兩個process都和外部的一個UTC時鐘源同步,並且process之間的誤差小於D
Internal Sync:兩個process之間相互同步,並且誤差小於D(即使可能這兩個process和UTC都有較大偏差)

幾乎所有號稱“同步”的分佈式系統,在實際中,都不是同步的,主要是因爲消息(包括用來同步時間的消息)傳送的延時是不可控的
用來同步時間的幾種算法
Cristian 算法
弄一個time server和UTC device相連,向網絡上的其他server提供time 服務
簡單流程爲,Server發一個消息Mr給time server,Time Server回一個消息Mt,裏面帶上自己的當前之間Tc
然後對於Server來說,當收到Mt之後,判斷自己的時間:
1. 最簡單的方法:從中取出Tc,加上(round-trip time)/2 即爲自己的當前時間 => 這個假設round-trip time平均分配,去的時間 和 回的時間相等
2. 但是大多數case下,round trip來回的時間是不等的,所以改進算法爲
   => 通過理論值,算出round trip 的“單程”最小值 min,於是Time Server 發送 Mt的最早時間爲t+min,最晚時間爲t+roundtrip-min
   於是對於自己的Server來說,當收到消息Mt,取出其中的Tc的實際時間的可能範圍爲[Tc+min, Tc+roundtrip-min] => 這個區間的範圍爲roundtrip-2xmin,所以可以認爲這種算法的精度爲 “正負”roundtrip/2-min

實際使用中,可以多測幾次roundtrip數值,防止間斷性的網絡阻塞影響roundtrip短暫性的很大

Cristian算法的一個問題是,如果Time Server壞了,就都完蛋了
於是演進算法Berkeley 算法,大致思想爲(Internal Sync)
一組Server,選舉一個做爲Master,其他爲Slave,Master用Cristian算法問Slave要時間
然後Master對取來的時間做個平均值,得出一個“準確的時間”,
同時再把這個“準確的時間”和各個Slave之間的差值送還給Slave,用來修改他們自己的時間
這裏一個潛在的問題是,“平均”算法,如果某個“採樣值”太不靠譜,會極大影響整個平均值=> 算法會加以控制,如果某個採樣的offset太大,則丟棄

然後再演進,就是NTP
分層不用說了
NTP的三種模式,multicast、procedure call、symmetric mode,從左往右,精度越來越高
multicast通常用在高速的LAN之中,假設網絡延遲很小,Timerserver廣播自己的時間
procedure call就類似Cristian算法,Timesever應答來自client的request,返回自己的時間,精度高於multicast
symmetric mode(對稱模式?),貌似是有2個Timerserver,分別從更高層拿時間,同時這兩個server之間做消息交互,確保時間一致
A pair of servers operating in symmetric mode exchange messages bearing timing information. Timing data are retained as part of an association between the servers that is maintained in order to improve the accuracy of their synchronization over time.

不管上面哪種模式,消息都是UDP的,那麼如何保證準確性呢?
spacer.gif
幾個概念
1. offset,指的是上面兩個server A和B的時鐘的actual offset
2. delay,di,指的是上面上面兩條m消息的總transmission時間
   其中m消息的transmission時間爲t,m’的transmission時間爲t’
。。。。
沒看懂。。。P606


邏輯時鐘
簡單講,就是用counter來表示邏輯順序=》KERN裏面好像有類似的機制,回頭翻翻
引入背景
1. single sever上面可以用本機物理時間來對事件進行排序 => ordering envents
2. 分佈式系統中,很顯然,因爲各機器物理時鐘不可靠(即使有NTP),所以無法用物理時間來對Event排序
於是,引入一個概念:happened-before relation, 經常又被叫做causal(因果關係) ordering or potential causal ordering
定義很簡單:發消息的event,總是先於收消息的event
(關於這個relation的一些注意點,例如下圖,即使A發先於F收,但是A和F是沒有因果關係的)
(再例如,也不是所有的event都能夠有這種關係,例如A和E)
spacer.gif

再有了上述happened-before relation的定義之後,引入logical clock概念
實現上,就是一個software counter,和physical clock沒任何關係
每個process有自己的 locial clock Li
對每個event,如果是發生的process pi上面的,我們用Li(e)來做標識它的“logical timestamp”;用L(e)來標識process無關的“邏輯時間戳”

實際操作過程中,例如發消息之前,把自己的Li+1,同時把這個數值和消息一塊發過去
收消息的時候,解出消息裏面對方的counter值,和自己的當前值比較,從而得到“邏輯上的時間先後關係”

在logical clock中
如果e->e', 那麼一定能推出L(e) < L(e')
但是反之不能從L(e) < L(e') 推出e->e' (因爲e和e')可能沒有這種因果關係,例如下圖的b和e
spacer.gif


爲了解決這個問題,推出了vector clock的概念。。
舉例如下
在一個有N的process的分佈式系統中(例如下圖N=3),vector clock是一個有N個整數的數組
每當有event發生的時候,加減關係如下圖所示(每個process只增加屬於自己的那一位)
spacer.gif
當P1發消息給P2的時候
P1把vector clock中屬於自己的那一位+1
P2收到的時候,比較自己的vector clock裏面“屬於P1的那一位”和P1這次發來的消息中的“屬於P1的那一位”的大小,留下大的數值
=> 這樣得到的效果是,對每個process的vector clock,屬於自己的那一位,總是自己發送消息的數目;屬於別的process的那一位,總是那個process發出的影響到自己的消息的數目
=> KERN的DB裏面一定有類似的算法,好像是用來做同步的,翻一下

回到引入Vector Clock的初衷=> logical clock中不能從L(e) < L(e') 推出e->e'
只要給出vector clock比較大小的算法,這個問題就很容易解決了
spacer.gif

=> 例如上圖中的c和e點,從V的比較上來說,只能落入上面的第三行 => 這說明,他們是並行發生的。

全局狀態管理(Global State)
先說問題
這塊最典型的問題例如“垃圾回收”
如下圖,爲了決定是否要回收某個對象,除了判斷本機的狀態,還要判斷其他server的狀態(例如P2引用了P1上面的對象),甚至消息,例如message裏面引用了P2裏面的對象 => 如果是在一個server上面,最簡單的方法是,確定一個時間,大家都上報自己的狀態,這樣就比較好判斷了
但是分佈式系統,各個server時間無法保證Perfect Sync,所以“限定一個時間,各自上報狀態”的方法無效。
(其他的例子,例如死鎖,以及無法終止“涉及多個Process的算法”=> 各方都處於passive狀態 => P611)
spacer.gif

解決這個問題=> 可以通過“local state" 來構造出global state
we might ask whether we can assemble a meaningful global state from local states recorded at different real times. The answer is a qualified
‘yes’

需要先加入幾個新概念
1. 單個Process的“歷史事件”
spacer.gif

2. 單個process的狀態定義:Si
spacer.gif

3. 對整個系統來說,整個系統的history => global history
spacer.gif

4. 對整個系統,針對History,給一個Cut的定義
A cut of the system’s execution is a subset of its global history that is a union of prefixes of process histories
spacer.gif
下面是兩種典型的Cut,一致性的cut和非一致性的cut
spacer.gif

區別在於,上面inconsistent的Cut的例子裏面,P1 還沒有發送消息,但是cut裏面卻包含了“P2收到那個P1還沒有發送的消息”
正規一點的定義就是:對於consistent的cut,這個cut裏面的每個event,他們的happend-before event一定也包含在這個cut裏面

5. 再進一步“一致性的全局狀態”(Consistent Global State)對應的就是一系列Consistent Cut
於是整個系統的運轉就被抽象成了一組Consistent Global State之間的遷移
S0 -> S1 -> S2 ->...
上面的每個轉換之間可能發生的事情就例如收發消息,或者自己的internal event
如何用這個模型解決最開始的問題,垃圾回收,死鎖等等












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章