向量時鐘演算法
【轉自】http://blog.chinaunix.net/uid-27105712-id-5612512.html
一、使用背景
先說一下需要用到向量時鐘的場景。我們在寫資料時候,經常希望資料不要儲存在單點。如db1,db2都可以同時提供寫服務,並且都存有全量資料。而client不管是寫哪一個db都不用擔心資料寫亂問題。但是現實場景中往往會碰到並行同時修改。導致db1和db2資料不一致。於是乎就有人想出一些解決策略。向量時鐘算是其中一種。簡單易懂。但是並沒有徹底解決衝突問題,現實分散式儲存補充了很多額外技巧。
這裡反向敘述方式, 介紹向量時鐘。先舉實際例子讓讀者有個感性認識,然後再說演算法規則。
二、舉個例子
向量時鐘實際是一組版本號(版本號=邏輯時鐘),假設資料需要存放3份,需要3臺db儲存(用A,B,C表示),那麼向量維度就是3,每個db有一個版本號,從0開始,這樣就形成了一個向量版本[A:0, B:0, C:0];
Step 1: 初始狀態下,所有機器都是[A:0, B:0, C:0];
DB_A——> [A:0, B:0, C:0]
DB_B——> [A:0, B:0, C:0]
DB_C——> [A:0, B:0, C:0]
Step 2: 假設現在應用是一個商場,現在錄入一個腎6的價格iphone6 price 5888; 客戶端隨機選擇一個db機器寫入。現假設選擇了A。,資料大概是這樣 :
{key=iphone_price; value=5888; vclk=[A:1,B:0,C:0]}
Step 3: 接下來A會把資料同步給B和C;於是最終同步結果如下
DB_A——> {key=iphone_price; value=5888; vclk=[A:1,B:0,C:0]}
DB_B——> {key=iphone_price; value=6888; vclk=[A:1, B:0,C:0]}
DB_C——> {key=iphone_price; value=5888; vclk=[A:1,B:0,C:0]}
Step 4:過了分鐘,價格出現波動,升值到6888;於是某個業務員更新價格。這時候系統隨機選擇了B做為寫入儲存,於是結果看起來是這樣:
DB_A——> {key=iphone_price; value=5888; vclk=[A:1,B:0,C:0]}
DB_B——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
DB_C——> {key=iphone_price; value=5888; vclk=[A:1,B:0,C:0]}
Step 5:於是B就把更新同步給其他幾個儲存
DB_A——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
DB_B——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
DB_C——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
到目前為止都是正常同步,下面開始演示一下不正常的情況。
Step 6:價格再次發生波動,變成4000,這次選擇C寫入:
DB_A——> {key=iphone_price; value=6888; vclk=[A:1, B:1,C:0]}
DB_B——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
DB_C——> {key=iphone_price; value=4000; vclk=[A:1, B:1,C:1]}
Step 7: C把更新同步給A和B,因為某些問題,只同步到A,結果如下:
DB_A——> {key=iphone_price; value=4000; vclk=[A:1, B:1,C:1]}
DB_B——> {key=iphone_price; value=6888; vclk=[A:1,B:1,C:0]}
DB_C——> {key=iphone_price; value=4000; vclk=[A:1, B:1,C:1]}
Step 8:價格再次波動,變成6000元,系統選擇B寫入
DB_A——> {key=iphone_price; value=6888; vclk=[A:1, B:1,C:1]}
DB_B——> {key=iphone_price; value=6000; vclk=[A:1,B:2, C:0]}
DB_C——> {key=iphone_price; value=4000; vclk=[A:1, B:1,C:1]}
Step 9: 當B同步更新給A和C時候就出現問題了,A自己的向量時鐘是[A:1, B:1,C:1], 而收到更新訊息攜帶過來的向量時鐘是[A:1,B:2, C:0], B:2 比B:1新,但是C:0卻比C1舊。這時候發生不一致衝突。不一致問題如何解決?向量時鐘策略並沒有給出解決版本,留給使用者自己去解決,只是告訴你目前資料存在衝突。
三、規則介紹
版本號變更規則其實就2條,比較簡單
1、 每次修改資料,本節點的版本號 加1,例如上述step 8中 向B寫入,於是從B:1變成B:2,其他節點的版本號不發生變更。
2、 每次同步資料(這裡需要注意,同步和修改是不一樣的寫操作哦),會有三種情況:
a: 本節點的向量版本都要比訊息攜帶過來的向量版本低(小於或等於) 如本節點為[A:1, B:2,C:3]}, 訊息攜帶過來為[A:1, B:2,C:4]或[A:2, B:3,C:4]等。 這時候合併規則取每個分量的最大值。
b: 本節點的向量版本都要比比訊息攜帶過來的向量版本高,這時候可以認為本地資料比同步過來的資料要新,直接丟棄要同步的版本。
c: 出現衝突,如上述step 9中,有的分量版本大,有的分量版本小,無法判斷出來到底誰是最新版本。就要進行衝突仲裁。
四、衝突解決
其實沒有一個比較好的解決衝突的版本:就筆者目前所瞭解,加上時間戳算是一個策略。具體方法是再加一個維度資訊:資料更新的時間戳(timestamp)。[A:1, B:2,C:4,ts:123434354] ,如果發生衝突,再比較一下兩個資料的ts,大的數值說明比較後更新,選擇它作為最終資料。並對向量時鐘進行訂正。
五、其他問題
1、向量時鐘的維數和存放資料備份數目相等,如果備份數目太多。會導致向量太長。不過目前好像不會存在這個問題,一般備份數目=3就足夠。即使再多幾份,也不會太長。
2、 衝突糾錯時,矯正方有很多:有的放在後臺服務端矯正,有的交給客戶端來矯正,譬如客戶端仲裁後,寫回服務端。糾錯時機也有很多,有點在讀資料是發現資料不一致進行糾正,有的是同步時候發現不一致糾正。實際實現大家自己選擇。
相關文章
- 向量時鐘演算法簡介演算法
- 分散式系統:向量時鐘分散式
- 實現一個CRDT工具庫——VClock 時鐘向量類
- 求鐘錶時針和分鐘夾角演算法問題演算法
- 系統時鐘與硬體時鐘
- 分散式系統的硬核:時間時鐘問題和演算法分散式演算法
- 實時時鐘、系統時鐘和主機伺服器時鐘的區別伺服器
- 網路精確時鐘 2.25註冊演算法分析演算法
- 支援向量機(五)SMO演算法演算法
- Linux 系統時鐘和硬體時鐘Linux
- CSS動畫篇之炫酷時鐘之時鐘牆CSS動畫
- 硬體時鐘與系統時鐘同步問題
- 分類演算法-支援向量機 SVM演算法
- 支援向量機|SMO演算法實現演算法
- 時鐘——CSS 動畫CSS動畫
- NTP時鐘同步
- solaris同步時鐘
- 網頁時鐘網頁
- SVM 支援向量機演算法-原理篇演算法
- SVM 支援向量機演算法-實戰篇演算法
- 支援向量機原理(四)SMO演算法原理演算法
- 演算法金 | 再見,支援向量機 SVM!演算法
- js年月日小時分鐘秒動態時鐘效果JS
- Linux 硬體時鐘和系統時鐘 - hwclock介紹Linux
- Linux時鐘精度Linux
- 純JavaScript時鐘 (轉)JavaScript
- 運動的時鐘
- 簡黑時鐘AClock 2.3 Mac (Mac自定義全屏時鐘軟體)Mac
- Qt時鐘介面、數字時鐘(12小時制24小時制切換、修改系統時間)QT
- 【實時時鐘RTC】MSP430系統實時時鐘RTC學習日誌(完善中)
- canvas圓形時鐘效果Canvas
- canvas動態時鐘效果Canvas
- 數字時鐘DigClockGC
- 安卓之旅-時鐘開發安卓
- STM32時鐘配置
- 五分鐘搞懂摘要演算法演算法
- 10分鐘弄懂Raft演算法Raft演算法
- 機器學習演算法筆記之5:支援向量機SVM機器學習演算法筆記