著名的CAP理論,如圖所示
C:一致性。既更新和讀取的一致性。
P:分區容忍。既分佈式
A:可用性。(包括SLA和性能)
關於一致性:
客戶端側:
假設有三個進程PA,PB,PC。都具有向同一存儲的讀寫權限,PA寫入後。
1、若能保證PB,PC讀取到的都是PA的最新的更新。則實現了強一致性。
2、若從PA寫入,到PB、PC能夠讀取到最新數據之間,有時間。稱爲若一致性,之間的時間稱爲不一致性窗口。最終PA,PB,PC都能夠讀取到PA的更新,稱爲最終一致性。
3、通知PB,PB能夠PA最新更新的值。而PC只需要得到最終一致性。稱爲因果一致性。
4、PA總能讀到最新的值,稱爲讀己所寫一致性。
5、在PA與存儲系統的一個會話中都能保證讀己所寫一致性,則實現回話一致性。
6、某一進程,只要讀取到了最新的值,就不會再讀取到之前的值。稱爲單調讀一致性
7、PA的多次更新請求,存儲系統都能夠保證順序執行。則爲單調寫一致性
服務端側:
需要將更新發布到整個分佈式存儲,儘量減少不一致性窗口的大小。
N:數據複製的份數
W:更新數據時需要保證寫完成的節點數
R:讀數據時需要讀取的節點數
之間的關係是這樣的:
W+R>N,寫和讀節點重疊。強一致性。
W+R<=N,弱一致性
W越大,可用性越低。
比如hdfs,N=3,W=3,R=1。寫一份數據成功,需要將3個datanode都寫成功,讀取是客戶端選擇讀取一datanode。所以hdfs是一個偏重CP滴。
一般可用性和一致性平衡的值是W=R=N/2+1
關於RAM和磁盤的名言:
「內存是新的硬盤,硬盤是新的磁帶」「對於隨機訪問,硬盤慢得不可忍受;但如果你把硬盤當成磁帶來用,它吞吐連續數據的速率令人震驚;它天生適合用來給以RAM爲主的應用做日誌(logging and journaling)。」
分佈式的分佈算法發展:
第一階段:hash() mod n,n爲節點數。這種分佈方法會造成單點故障。
第二階段:hash() mod (n/2)。每個key可以對應兩個節點。client可隨機選擇,在一個不可用時,可切換下一個。利用hash算法硬編碼實現負載的最大弊端是無法在不停服務的情況下動態增刪節點。
第三階段:一致性hash算法。如下圖所示
實現上述一致性的算法:
vector clock:所有節點都記錄自己的版本信息,用一個vector來記錄所有的變更記錄。W=1,R=N=3的情況。如下圖所示:
讀取是從三個節點讀取,根據版本取捨和合並需要應用解決。所以最好使用W=N,簡化系統設計(犧牲可用性)。
Gossip協議(狀態轉移模式):
每個節點都保持一個Vector clock和state version tree。在一定的時間窗之後,每個節點的狀態是相同的,state version tree包含所有的衝突update。狀態同步的階段和算法大致如下:
1、客戶端查詢:客戶端帶自己的vector clock發送複製節點(一個or所有?),節點返回在這個clock之前的vector clock列表,然後客戶端根據merge所有的列表跟新自己的vector clock
2、客戶端更新:客戶端發送自己的vector clock,接收到的節點就跟本地版本比較,若client版本比本地低,則丟棄,否則,更新。
3、節點間也交換vector clock來合併version tree。
Gossip協議(操作轉移模式):
暫時沒看
兩階段提交和三階段提交:
當集羣規模增大時,首先採取master/slaver架構,但是存在寫操作依賴master,存在單點故障。改進採用多master結構,每個master都有讀寫能力,就存在一致性的問題。可採用的一致性算法有兩階段提交和三階段提交。
兩階段提交:
一個或多個資源管理器的活動由一個成爲事務協調器的組件控制:
某班要組織一個同學聚會,前提條件是所有參與者同意則活動舉行,任意一人拒絕則活動取消。用2PC算法來執行過程如下
Phase 1
Prepare: 組織者(coordinator)打電話給所有參與者(participant) ,同時告知參與者列表。
Proposal: 提出週六2pm-5pm舉辦活動。
Vote: participant需vote結果給coordinator:accept or reject。
Block: 如果accept, participant鎖住週六2pm-5pm的時間,不再接受其他請求。
Phase 2
Commit: 如果所有參與者都同意,組織者coodinator通知所有參與者commit, 否則通知abort,participant解除鎖定。
Failure 典型失敗情況分析
Participant failure:任一參與者無響應,coordinator直接執行abort
Coordinator failure:
Takeover: 如果participant一段時間沒收到cooridnator確認(commit/abort),則認爲coordinator不在了。這時候可自動成爲Coordinator備份(watchdog)
Query: watchdog根據phase 1接收的participant列表發起query
Vote: 所有participant回覆vote結果給watchdog, accept or reject
Commit: 如果所有都同意,則commit, 否則abort。
兩階段提交的問題:在coordinator做出commit決策並開始發送commit之後,某個participant突然crash,這時候沒法abort transaction,
這時候集羣內實際上就存在不一致的情況,crash恢復後的節點跟其他節點數據是不同的。改進爲三階段提交。
缺點:網絡分離問題,比如preCommit消息發送後突然兩個機房斷開,這時候coodinator所在機房會abort, 另外剩餘replicas機房會commit。
真正一致性的算法paxos:(具體待補充)
存儲實現:
CouchDB(具體待補充)
在bigtable中,內存中存放的是最新的數據版本。當內存databuffer滿時,會在落地到磁盤新建dataset。當datatset過多時,合併。查詢時按照版本順序,即先讀取內存中的,若沒有再讀取本地磁盤的最新版本,若沒有再讀取次新版本,依此類推。當update數據時,更改內存中的數據,同時寫入commitlog中。