MVCC 事務機制3:混合邏輯時鐘
在前篇文章《MVCC事務機制2:邏輯時鐘》中講到,邏輯時鐘可能造成人在物理視角理解事務順序的不一致性,而物理時鐘雖然符合人的物理視角的一致性,但是沒有辦法保持整個系統(分散式)時鐘的一致性。混合邏輯時鐘則嘗試著解決物理時鐘和邏輯時鐘存在的問題。
混合邏輯時鐘演算法
混合邏輯時鐘為了解決邏輯時鐘和物理時鐘的問題,提供了單向的因果序列檢測和排序能力(邏輯時鐘能力),同時保持時鐘接近物理時鐘。在系統事件時間戳上描述採用了因果序列和物理時鐘的組合,而不是單純的物理時間或者單純的因果序列。 其演算法還是非常簡單:
混合邏輯時鐘的一個時間戳使用兩個值來表示 l,c Initially l.j :=0; c.j:0Send or local event l’.j : =l.j l.j = max(l’.j, pt.j) if (l.j = l’.j) then c.j := c.j+1 else c.j = 0 timestamp with = l.j c.j Receive event of message m l’.j := l.j l.j := max(l’.j, l.m, pt.j ) if (l.j = l’.j = l.m) then c.j: max (c.j,c.m) +1 else if (l.j =l’.j) then c.j := c.j+1else if (l.j = l.m) then c.j =c.m + 1 else c.j := 0 timestamp with l.j c.j pt 為物理時鐘
更多詳細資訊可以參考論文《Logical Physical Clocks and Consistent Snapshots in Globally Distributed Databases》。由上面演算法可知,混合邏輯時鐘實現了單向的因果檢測和排序,同時能夠修正時間不一致帶來的偏差。我們來看一個論文中的例子:
從演算法可以很清楚知道,它讓混合邏輯時鐘表示物理時鐘的值儘量與本地節點的物理時鐘保持一致,但是不依賴本地的物理時鐘,同時不用擔心本地時鐘的回退,如果和NTP結合使用時,又不用擔心NTP 跳變帶來的問題;混合邏輯時鐘表示的邏輯時鐘值是一個絕對值。 與Google True Time相比,不存在 True Time的overlap問題。
於是在諸多好處前景下,混合邏輯時鐘在很多資料庫中和一些分散式系統中得到廣泛的應用,比如CockroachDB,HDFS(一致性快照)。
我們再看看它的問題。
問題
由演算法可理解,混合邏輯時鐘演算法其實只關心兩種情況的先後順序:
-
在同一個程序或者執行緒中發生的事件的前後順序
-
程序之間傳送訊息與接收訊息這兩個事件的前後順序
如果把程序理解成系統的一個session,它內部的邏輯時鐘能夠保證session內事件的順序,比如在同一個session的先執行事務1,再執行事務2,我們會認為事務2一定是在事務1結束(提交或許abort)後開始執行的。 但是出現了跨session,特別是這個session 在系統外的節點(application 呼叫系統的介面)這個前後關係就很難得不到保證。舉個例子:
-
session1 session2 都在分散式系統內的節點,而Application部署在分散式節點之外的節點上。
-
在物理時間上:Application先在session1 執行txn1,Application接收到txn1 committed訊息後,再在session2 上執行txn2. Application在物理視角看起來,txn2的開始時間一到晚於txn1的提交時間。
-
在邏輯時鐘上, 完全有可能存在session2 的開始時間要早於session1 的提交時間。
混合邏輯時間可以讓邏輯時鐘的值儘量等於本地物理時鐘的值,但是它從本質上還是邏輯時鐘的演算法,在物理時鐘的偏差範圍內,依然存在上述問題。
這帶來一個新的問題:系統執行結果的正確性是否依賴事務之間的先後順序(同一個session 之間的事務的先後順序可以保證,但是不同的session之間的先後順序無法保證)。
但是,如果要保證不同的session之間的事務執行的順序,怎麼辦?兩種可能的解決方法:
-
把Application的節點包含在邏輯時鐘的分散式系統之內。
-
使用帶時間視窗的混合邏輯時鐘。
方法1對系統的入侵性太大,雖然能夠解決問題,但是太不實用。方法2似乎只有Google True Time解決了,可惜沒有開源。
總結
混合邏輯時鐘可以保證同一個process內部事件的先後順序,但是解決不了系統外事件發生邏輯前後順序與物理時間前後順序的一致性。即使存在這樣的問題,Cockroach依然還在使用該機制,下篇文章講介紹Cockroach mvcc實現流程。