天天看點

Amazon Dynamo的NWR模型

Amazon Dynamo的NWR模型,把CAP的選擇權交給了使用者,讓使用者自己選擇CAP中的哪兩個。

N代表N個副本(replication),W代表寫入資料時至少要寫入W份副本才認為成功,R表示讀取資料時至少要讀取R份副本。對于R和W的選擇,要求W+R > N。 

優化寫性能(AP)

當我們需要優化寫性能(寫多讀少)的時候,可以配置W = 1 (寫完一個副本就成功,其他的副本就異步去慢慢複制都可以),如果N=3,那麼根據公式W+R>N,則R = 3(讀取資料的時候需要讀3個副本以判斷資料是否有沖突)。 這種情況隻要寫任何節點成功就認為成功,但是讀的時候必須從所有的節點都讀出資料。

優化讀性能(CP)

當我們需要優化讀性能(讀多寫少)的時候,可以配置 W=N(寫完所有的副本才成功,隻能同步複制),根據公式W+R>N,則 R=1(隻需讀一個副本即可)。這種情況任何一個節點讀成功就認為成功,但是寫的時候必須寫所有三個節點成功才認為成功。

平衡讀寫性能(AC)

當我們資料不多,單台能搞定,且不需要容錯和擴充性的時候,可以配置N=1(隻有一份資料),根據公式W+R>N,則W=1,R=1。這種情況就簡化為單機問題了。

多個線程會同時更新一份資料,在這種情況下怎麼保證一緻性?

Amazon Dynamo使用多版本并發控制,即樂觀鎖。如果使用者A讀出來的資料的版本是v1,當使用者A計算完成後要更新資料時,卻發現資料的版本号已經被更新成了v2,那麼伺服器就會拒絕更新導緻更新失敗,這時候就需要使用者A自己處理沖突,方法為:重新讀取v2資料,然後重新計算,重新更新。這裡跟在svn送出代碼發生沖突的情況是一樣的,svn送出代碼遇到沖突,需要先更新代碼,解決沖突之後才能再次送出。

如何發現不同節點上面的副本不一緻?

還有更糟糕的時候(W=1),使用者A更新一個副本,在A的更新還沒有異步複制到其他副本之前,如果使用者B也更新了其他副本,那麼資料就處于不一緻的狀态了,同樣需要使用者自己處理。

Amazon  Dynamo使用Vector Clock(向量時鐘)。每個節點各自記錄自己的版本資訊,包括:1)更新資料的節點名稱,2)版本号。

如下所示,有A、B和C三個節點,W=1,R=N=3:

  1. (節點A寫了兩次)一個寫請求,第一次被節點A處理了。節點A會增加一個版本資訊(A,1)。我們把這個時候的資料記做D1(A,1)。 然後另外一個對同樣key的請求還是被節點A處理了于是有D2(A,2)。這個時候,D2是可以覆寫D1的,不會有沖突産生。
  2. (節點A的資料成功異步複制到節點B和節點C,節點A、節點B、節點C處于一緻)現在我們假設D2異步複制到了所有其他節點(節點B和節點C),節點B和節點C收到的資料不是來自使用者,而是由節點A異步複制(為了讓所有副本保持一緻)來的,是以節點B和節點C不産生新的版本資訊,是以現在節點B和節點C所持有的資料還是D2(A,2)。于是節點A,節點B,節點C上的資料及其版本号都是一樣的。
  3. (節點B寫了一次)如果有一個新的寫請求到了節點B上,于是節點B生成資料D3(A,2; B,1),意思是:資料D全局版本号為3,節點A更新了2次,節點B更新了1次。
  4. (節點C寫了一次:節點B的改變還沒異步複制到節點C之前節點C就寫完了)如果D3還沒有異步複制到節點C的時候,節點C又處理了一個新的寫請求,于是,節點C上的資料是D4(A,2; C,1)。
  5. 好,最精彩的事情來了:如果這個時候來了一個讀請求,因為W=1,R=N=3,是以R會從所有三個節點(A、B、C)上讀,此時,他會讀到三個版本:
  • A結點:D2(A,2)
  • B結點:D3(A,2; B,1);
  • C結點:D4(A,2; C,1)

  6.這個時候可以判斷出,D2已經是舊版本(已經包含在D3/D4中),可以舍棄。

  7.但是D3和D4是明顯的版本沖突,隻能交給使用者自己去做版本沖突管理。就像前面說的svn源代碼版本管理一樣。

繼續閱讀