分佈式事務實現-Spanner

  Spanner要知足的external consistency是指:後開始的事務必定能夠看到先提交的事務的修改。全部事務的讀寫都加鎖能夠解決這個問題,缺點是性能較差。特別是對於一些workload中只讀事務佔比較大的系統來講不可接受。爲了讓只讀事務不加任何鎖,須要引入多版本。在單機系統中,維護一個遞增的時間戳做爲版本號很好辦。分佈式系統中,機器和機器之間的時鐘有偏差,而且偏差範圍不肯定,帶來的問題就是很難判斷事件發生的先後關係。反應在Spanner中,就是很難給事務賦予一個時間戳做爲版本號,以知足external consistency。在這樣一個偏差範圍不肯定的分佈式系統時,一般,得到兩個事件發生的前後關係主要經過在節點之間進行通訊分析其中的因果關係(casual relationship),經典算法包括Lamport時鐘等算法。然而,Spanner採用不一樣的思路,經過在數據中心配備原子鐘和GPS接收器來解決這個偏差範圍不肯定的問題,進而解決分佈式事務時序這個問題。基於此,Spanner提供了TrueTime API,返回值實際爲一個區間[t-ε,t+ε],ε爲時間偏差,毫秒級,保證當前的真實時間位於這個區間。算法

  Spanner是一個支持分佈式讀寫事務,只讀事務的分佈式存儲系統,只讀事務不加任何鎖。和其餘分佈式存儲系統同樣,經過維護多副原本提升系統的可用性。一份數據的多個副本組成一個paxos group,經過paxos協議維護副本之間的一致性。對於涉及到跨機的分佈式事務,涉及到的每一個paxos group中都會選出一個leader,來參與分佈式事務的協調。這些個leader又會選出一個大leader,稱爲coordinator leader,做爲兩階段提交的coordinator,記做coordinator leader。其餘leader做爲participant。數據庫

  數據庫事務系統的核心挑戰之一是併發控制協議。Spanner的讀寫事務使用兩階段鎖來處理。詳細流程下圖所示。併發

  如第一段所述,給事務賦予一個時間戳版本號是這樣一個分佈式存儲系統的核心。下面先說如何肯定讀寫事務的版本號,再說只讀事務。app

  前面已經說了兩階段提交過程當中兩階段鎖的過程,這裏就省略這些,只討論兩階段提交過程當中如何肯定最後的讀寫事務的時間戳版本號。分佈式

  讀寫事務ide

 

 

 

 

 

 

簡要時序圖以下:性能

  

 

圖中,commit wait分爲兩段,第一階段是論文中4.1.2節提到的Start,第二階段是4.1.2節的Commit Wait google

只讀事務spa

   調用TrueTime API,將右區間做爲只讀事務的版本號,記做Sread, 若是讀事務涉及到的副本不夠新,那麼讀會阻塞。每一個副本會維護一個時間戳Tsafe, 若是Sread <= Tsafe ,則這個副本夠新。Tsafe取兩個時間戳的更小值,第一個是副本所在的paxos group中已經apply到狀態機的時間戳,第二個是paxos group中leader目前正在參與的尚未commit的分佈式事務在該paxos group的最小的prepared timestamp - 1。.net

   還有一種方法,能夠不用客戶端等,方法是Sread經過客戶端和全部涉及到的paxos group的leader進行協商,每一個leader返回他們的最後一次事務的commit時間戳給客戶端,而後客戶端取最小的版本號做爲Sread便可。

下面說一下兩階段提交的錯誤處理。

  兩階段提交協議因爲協調者和參與者的故障可能會有嚴重的可用性問題。Spanner的兩階段提交實現基於Paxos協議,每一個participant和coordinator自己產生的日誌都會經過paxos協議複製到自身的paxos group中,從而解決可用性問題。一樣以A,B,C三份數據爲例,他們分別有三個副本,記做(A1,A2,A3),(B1,B2,B3),(C1,C2,C3),每組做爲一個paxos group,內部經過paxos協議保證一致性。假設,A1,B1,C1分別爲各自paxos group的leader,A1爲coordinator leader。

  Prepare階段:A1給B1和C1發送prepare消息後,假設B1掛了,A1等待超時,A1給C1發送rollback。B1後續回滾分爲兩種狀況:1. B1在持久化prepare消息以前掛了,B1恢復後可自行回滾 2. 若是B1持久化prepare消息以後掛了,B1自身能夠回放日誌得知事務未決,主動聯繫(A1,A2,A3)。A1給B1,C1發送prepare消息以後,本身掛了,一樣,A1經過回放日誌能夠得知。實際上,A1自己掛了以後,A2和A3經過選主協議立刻會選出一個新的leader,不至於影響到可用性。

   Commit階段:A1給B1,C1發送commit消息,B1 commit成功,C1掛了,C1起來後,若是C1以前沒有持久化commit消息,則A1主動要求C1繼續commit。若是C1以前已經持久化了commit消息,則本身commit。若是C1因爲某些緣由,始終commit不成功,則由上層業務進行回補操做。

 

參考資料

Spanner: Google’s Globally-Distributed Database

presentation:Spanner: Google’s Globally-Distributed Database

相關文章
相關標籤/搜索