動機
整理常見分散式設計手法
原子性
每一步都是一次到位或是根本沒有做
對時間建模
條件:
時間嚴格遞增
同一個時間下,所有人見到的時間一致
lamport clock
clk++
max(其他人的clk, 自己的clk)+1
vector clock
- 紀錄每個人的clk
法定人數 (quorum)
只有在同樣的動作到法定人數的承認才做 (多數決)
這樣可以確保至少每一次的動作至少有一個人是知道前一次操作的
法定人數 + 對時間建模 = read quorum
user拿到許多response,要怎麼確認是最新的? 就是留下時間,這裡通常叫version,但其實就是lamport clock
anti-entropy (recovery)
user拿到最新的結果,可以write回去
提到anti-entropy,可以講到Dynamo
Dynamo是只有法定人數去調整一致性 在衝突處理是用vector-clock之後配合user自己選
在做recovery是用Merkle tree去比對不同node之間的key是不是不同 Merkle tree就是一顆一直hash組成tree node的tree Merkle tree的好處是不用拿所有hash過的資料就可以找出是不是與tree持有的hash不同
像下面的就是只要有root,hash(AB),hash(C),資料D,就能確認資料D的版本對不對
write quorum的問題
但如果同時有人拿同一個lamport clock去寫? 所以需要quorum給承諾,這個lamport clock只有我可以用,同時你不能吃<=這個clock的資料 而這個就是2 phase commit
2 phase commit (2PC)
- prepare
- 問大家都ok嗎?
- 回ok
- client在回ok前要保證
- 當下的state是ok的
- 不論如何,都不會忘記當下的狀態
- 之後就是等
- client在回ok前要保證
- 回abort
- 就讓所有人abort
- 回ok
- 問大家都ok嗎?
- commit
- 讓大家commit
3 phase commit (3PC)
2PC有個問題是如果回ok之後就是等,但
- 如果問的人掛了
- 有人就是不回
其他人就是等到死
所以3PC加入pre-prepare
- pre-prepare
- 問大家都ok嗎?
- 回ok
- client在回ok前要保證
- 當下的state是ok的
- 不論如何,都不會忘記當下的狀態
- 之後就是等
- client在回ok前要保證
- 回abort
- 就讓所有人abort
- 回ok
- 問大家都ok嗎?
- prepare
- 問大家都ok嗎?
- 回ok
- 自己出事不回
- 問大家都ok嗎?
- commit
- 讓大家commit
因為有了pre-prepare的保證,所以其他人可以在回了commit之後等
- 問的人
- timeout
其中一個觸發來完成commit
租約
每個node想確認其他node有沒有出事的其中一種手段,其實就是timeout
例子
- 分散式鎖
- 原子性
- 對時間建模
- redlock: wall time
- zookeeper: file exist (or filename上有id)
- chubby: lock id
- paxos
- 法定人數
- 對時間建模
- 2 phase commit
- raft、zab
- paxos
- 租約 (確認leader還活著)
- 題外話
- 分散式事務 (事務的法定人數就是所有人,事務的時間就是commit或abort)
- 2 phase commit